将(f + g)定义为(f + g)(x):= f(x)+ g(x)。常规矩阵加法与此定义一致。
这是一个天真的实现
template<typename Funcf, typename Funcg>
auto operator+(Funcf f, Funcg g){
return [f, g](auto x){return f(x) + g(x);};
}
此操作失败,因为operator+
仅使用用户定义的类型。下一次尝试给出了
template<typename R, typename I>
auto operator+(std::function<R(I)> f, std::function<R(I)> g){
return [f, g](auto x){return f(x) + g(x);};
}
这可以工作,它不会乱丢命名空间。然而,它很多,并且呼叫站点是丑陋的auto added = std::function<int(int)>{f} + std::function<int(int)>{g};
。
如果允许第一个operator+
(或重命名为添加),则调用站点会更好,并且函数将被内联。但它试图与所有东西相匹配,这似乎很脆弱。
是否可以定义一个模板接口,该接口指定输入是函数,仍然内联它们,但不会使用过于通用的名称污染命名空间?
换句话说,是否有std::function
的编译时版本以及更方便的呼叫站点?我强烈怀疑答案是否定的。如果答案是否定的,那么上述两个极端之间是否有妥协?
或者选项三,我是否以错误的方式思考这个问题?你会如何在c ++中建模(f + g)?
答案 0 :(得分:1)
运算符仅适用于用户定义的类型。那么让我们来做你的功能吧!
我们可以定义一个基本上是lambda的类型,但是具有用户定义的类型名称:
template<typename F>
struct addable_lambda_impl : F {
template<typename T>
addable_lambda_impl(T f) : F{std::move(f)} {}
using F::operator();
};
template<typename F>
addable_lambda_impl<F> addable_lambda(F f) {
return addable_lambda_impl<F>{std::move(f)};
}
这是一个可以扩展任何类型的类,并将使用它的operator()
函数。
现在,您可以使用addable_lambda
功能:
auto lambda = addable_lambda([](){});
实施您的运营商也很容易:
template<typename F, typename G>
auto operator+(addable_lambda_impl<F> f, addable_lambda_impl<G> g){
return addable_lambda([f, g](auto x){ return f(x) + g(x); });
}
它并不完美,但稍微不那么难看。另外,您不会受到std::function
添加的开销。