我的工作“LINQ到对象”库,用于C ++ 11。 我想这样做水木清华这样的:
// filtering elements by their value
arr.where( [](double d){ return d < 0; } )
// filtering elements by their value and position
arr.where( [](double d, int i){ return i%2==0; } )
我倒想写arr.where_i( ... )
-它是丑陋的。 所以我需要通过拉姆达型函数/方法重载...
这是我的解决方案:
template<typename F>
auto my_magic_func(F f) -> decltype(f(1))
{
return f(1);
}
template<typename F>
auto my_magic_func(F f, void * fake = NULL) -> decltype(f(2,3))
{
return f(2,3);
}
int main()
{
auto x1 = my_magic_func([](int a){ return a+100; });
auto x2 = my_magic_func([](int a, int b){ return a*b; });
// x1 == 1+100
// x2 == 2*3
}
它是SFINAE解决方案吗? 你能建议我?
也许一些可变参数:
#include <utility>
template <typename F, typename ...Args>
decltype(f(std::declval<Args>()...) my_magic_func(F f, Args &&... args)
{
return f(std::forward<Args>(args)...);
}
编辑:您还可以使用typename std::result_of<F(Args...)>::type
的返回类型,它做同样的事情。
你一定要SFINAE在您的解决方案。 一般来说,结果看起来是这样的:
template<
typename Functor
, typename std::enable_if<
special_test<Functor>::value
, int
>::type = 0
>
return_type
my_magic_func(Functor f);
template<
typename Functor
, typename std::enable_if<
!special_test<Functor>::value
, int
>::type = 0
>
return_type
my_magic_func(Functor f);
这样,只有一个过载会活跃在任何一个时间-这一切仍然正在认真起草该special_test
有我们想要的行为。 这是因为你不想测试太具体了仔细的平衡; 否则就失去普遍性。 编写通用代码时,真丢人。 您还没有给出太多的信息(例如你在支持严格兴趣的lambda表达式?单形仿函数?多态性函子?),但我会承担,现在我们有机会获得一个value_type
别名,这将相当于double
在你的榜样。
因此,这里的一个例子条件,将检查给定的类型是可调用(这是一个标准的概念)与签名bool(value_type)
; 也就是说,它是某种形式的谓语:
template<typename Functor, typename ValueType>
struct is_unary_predicate {
typedef char (&accepted)[1];
typedef char (&refused)[2];
void consume(bool);
template<
typename X
, typename Y
, typename = decltype( consume(std::declval<X>()(std::declval<Y>())) )
>
accepted
test(X&&, Y&&);
refused test(...);
static constexpr bool value =
sizeof test(std::declval<Functor>(), std::declval<ValueType>())
== sizeof(accepted);
};
我个人有一个is_callable<F, Signature>
性状,这样我只需要编写类似template<typename Functor, typename ValueType> using is_unary_predicate = is_callable<Functor, bool(ValueType)>;
(类似地,我可以有一个is_binary_predicate
而不是让的第二过载别名my_magic_func
是捕获所有)。 也许你会想使用SFINAE的未来使用类似的特征(虽然它可能会有些痛苦,而不可变参数模板写)。