我已经编写了这个仿函数来执行和操作(&& ):
// unary functor; performs '&&'
template <typename T>
struct AND
{
function<bool (const T&)> x;
function<bool (const T&)> y;
AND(function<bool (const T&)> xx, function<bool (const T&)> yy)
: x(xx), y(yy) {}
bool operator() ( const T &arg ) { return x(arg) && y(arg); }
};
// helper
template <typename T>
AND<T> And(function<bool (const T&)> xx, function<bool (const T&)> yy)
{
return AND<T>(xx,yy);
}
注意它的构造函数参数类型:function<bool (const T&)>
。
现在,我试图以各种方式(在big_odd_exists()
内)实例化它:
int is_odd(int n) { return n%2; }
int is_big(int n) { return n>5; }
bool big_odd_exists( vector<int>::iterator first, vector<int>::iterator last )
{
function<bool (const int &)> fun1 = is_odd;
function<bool (const int &)> fun2 = is_big;
return any_of( first, last, And( fun1, fun2 ) ); // instantiating an And object
}
int main()
{
std::vector<int> n = {1, 3, 5, 7, 9, 10, 11};
cout << "exists : " << big_odd_exists( n.begin(), n.end() ) << endl;
}
令我惊讶的是,std::functions
的隐式实例化都不会编译。
以下是我尝试过的案例(g ++ - 4.8):
std::function
对象):function<bool (const int &)> fun1 = is_odd;
function<bool (const int &)> fun2 = is_big;
return any_of( first, last, And( fun1, fun2 ) );
std::function
对象):return any_of( first, last, And( is_odd, is_big ) ); // error: no matching function for call to ‘And(int (&)(int), int (&)(int))’
std::function
对象):function<bool (const int &)> fun1 = bind(is_odd,_1);
function<bool (const int &)> fun2 = bind(is_big,_1);
return any_of( first, last, And(fun1, fun2) );
std::function
对象):return any_of( first, last, And(bind(is_odd,_1), bind(is_big,_1)) ); // error: no matching function for call to ‘And(std::_Bind_helper<false, int (&)(int), const std::_Placeholder<1>&>::type, std::_Bind_helper<false, int (&)(int), const std::_Placeholder<1>&>::type)’
据我了解,std::functions
做不有明确的构造函数。
那么,为什么我不能使用 nicer来读取版本的调用?
我有所有的测试用例: http://coliru.stacked-crooked.com/a/ded6cad4cab07541
答案 0 :(得分:6)
问题是在这种情况下无法推断出T
。让我们从编译器的角度来看待它:
template <typename T>
AND<T> And(function<bool (const T&)> xx, function<bool (const T&)> yy)
// Later, invoked as:
And( is_odd, is_big )
“嗯,没有T
在通话中被指定,我将不得不推断它。参数是什么?is_odd
,它被拒绝输入int (*)(int)
。现在,我会必须为所有可能的std::function<bool (const T&)>
值实例化T
,并查看可以从int (*)(int)
类型中构造哪个/如果有的话。嗯,其中有无数的不会这样做的。“
如果您明确指定T
tempalte参数,它将起作用:
return any_of( first, last, And<int>( is_odd, is_big ) );
请注意,即使您更改了is_odd
和is_big
以完全匹配function
签名(返回bool
并取const int&
),这也会成立。这就是问题所在的推论。
答案 1 :(得分:2)
我建议不要滥用std::function
并改为使用普通的通用参数。将std::function
视为类型删除的容器,用于特定签名的可调用对象(有关详细信息,请参阅https://stackoverflow.com/a/11629125/46642)。
// unary functor; performs '&&'
template <typename X, typename Y>
struct AND
{
X x;
Y y;
template <typename XX, typename YY>
AND(XX&& xx, YY&& yy)
: x(std::forward<XX>(xx)), y(std::forward<YY>(yy)) {}
template <typename T>
auto operator() ( const T &arg ) -> decltype(x(arg) && y(arg))
{ return x(arg) && y(arg); }
};
template <typename T>
using Decay = typename std::decay<X>::type;
// helper
template <typename X, typename Y>
AND<Decay<X>, Decay<Y>> And(X&& xx, Y&& yy)
{
return AND<Decay<X>, Decay<Y>>(std::forward<X>(xx), std::forward<Y>(yy));
}