0

我正在玩一些代码,我对一些东西有点困惑。这是一个简化的示例:

我有Nodes它执行算术运算(加法,减法等)。我有一个容器,其中包含我的程序中可用的不同操作。这是一个例子:

typedef std::binary_function<double, std::vector<double>&, std::vector<Node*>& > my_binary_function;
auto const & product = [](double v, Node* n){ return v * n->GetEvaluation(); };
struct addition : public my_binary_function {
double
    operator()(std::vector<double>& weights, std::vector<Node*>& subtrees) {
        return std::inner_product(weights.begin(), weights.end(), 
        subtrees.begin(), 0, std::plus<double>(), product);
    }
};

现在,此时有两种选择:

1)使用函数类型:

typedef double (*my_function)(std::vector<double>&, std::vector<Node*>&);

然后使用以下模板化函数来转换函子:

template<typename F> typename F::result_type
func(typename F::first_argument_type arg1, typename F::second_argument_type arg2) {
    return F()(arg1, arg2);
}

2)使用函数包装类型,即std::function,这样我就有

typedef std::function<double (std::vector<double>&, std::vector<Node*>&)> my_function;

这一切都归结为这样的事情:

LoadDefaultFunctions() {
    int minArity = 2;
    int maxArity = 2;
    function_set_.AddFunction("Add", func<addition> , minArity, maxArity, 1.0); // case 1
OR
    function_set_.AddFunction("Add", addition(), minArity, maxArity, 1.0); // case 2

现在的问题是:

a) 如果我使用方法 1,我会收到以下编译错误:

error: invalid initialization of non-const reference of type 
'std::binary_function<double, std::vector<double>&, 
std::vector<Node*>&>::result_type {aka std::vector<Node*>&}' 
from an rvalue of type 'double'

如果我更改模板,错误就会消失(请注意参数现在没有真正意义):

template <typename F> typename F::first_argument_type
func1(typename F::second_argument_type arg1, typename F::result_type arg2) {
    return F()(arg1, arg2); 
}

我觉得很奇怪,因为对于其他类型,例如binary_op<double, double, double>,第一种形式可以正常工作。那么,发生了什么事?

b) 1) 比 2) 快(小幅度)。我在想我可能错过了一些通过引用传递函子的巧妙技巧,或者以某种方式可以std::function更有效地包装它。有任何想法吗?

c) 如果我使用 2) 中的 typedef,但另外我仍然使用func函子产生一个函数,然后std::function处理它,它仍然比 2) 快。那是:

`my_function = func<addition>` is faster than `my_function = addition()`

如果有人能帮助我理解这一切背后的机制,我将不胜感激。

谢谢。

4

1 回答 1

2

b) 1) 比 2) 快(小幅度)。我在想我可能错过了一些通过引用传递函子的巧妙技巧,或者以某种方式使 std::function 能够更有效地包装它。有任何想法吗?

是的,我希望 1 比 2 快。std::function执行类型擦除(存储的可调用的确切类型不存在于封闭std::function类型中),这需要使用虚函数调用。另一方面,当您使用模板时,确切的类型是已知的,编译器有更大的机会内联调用,使其成为一种免费的解决方案。这与您如何传递函子无关。

错误

模板参数的顺序不正确:

typedef std::binary_function<double,                 // arg1
                             std::vector<double>&,   // arg2
                             std::vector<Node*>&     // return type
                            > my_binary_function;

struct addition : public my_binary_function {
    double                                           // return type
    operator()( std::vector<double>& weights,        // arg1 
                std::vector<Node*>& subtrees)        // arg2
    { ...

也就是说,继承 frombinary_function正在向您的类添加一些 typedef,但这些不是正确的 typedef。然后,当您在下一个模板中使用 typedef 时,类型不匹配。该模板期望您operator()将返回 a std::vector<Node*>&,这是 的返回类型func,但是当您调用仿函数时,您得到的是 a double,这会导致错误:

std::vector<Node*>&... from的无效初始化double

于 2012-05-20T00:06:45.257 回答