我正在玩一些代码,我对一些东西有点困惑。这是一个简化的示例:
我有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()`
如果有人能帮助我理解这一切背后的机制,我将不胜感激。
谢谢。