3

我编写了这个函子来执行操作(&&):

// 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

4

2 回答 2

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,它被衰减为 type int (*)(int)。现在,我必须实例化std::function<bool (const T&)>所有可能的T值并查看可以构造哪个/如果有的话从 type int (*)(int)。嗯,有无数个。不会这样做。“

T如果您明确指定tempalte 参数,它将起作用:

return any_of( first, last, And<int>( is_odd, is_big ) );

活生生的例子


请注意,即使您更改is_odd并完全is_big匹配function签名(返回bool和获取const int&),这仍然成立。问题出在扣款上。

于 2013-10-16T10:32:41.053 回答
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));
}
于 2013-10-16T14:34:59.573 回答