我们说我有2个仿函数add和mult。 /img/smpl4.jpg
和add2(x) = x+2
。
我想创建一个组合张量mult3(x) = 3x
,使t
。
我提出了创建对仿函数的解决方案,但我不太满意,因为这个解决方案不能扩展到更多的仿函数。
我有什么选择?
t(x) = x+2 + 3x
答案 0 :(得分:1)
名称pair
对于仿函数的作用并不重要。我认为按照以下方式创建一些东西是有意义的:
template<typename T1, typename T2>
struct plus
{
plus(T1 t1, T2 t2) : t1_(t1), t2_(t2) {}
double operator()(double x)
{
return t1_(x) + t2_(x);
}
T1 t1_;
T2 t2_;
};
并提供一个辅助函数来创建这种类型的实例。
template<typename T1, typename T2>
plus<T1, T2> make_plus(T1 t1, T2 t2)
{
return plus<T1, T2>(t1, t2);
}
然后,您可以使用:
add add2 = add(2);
mult mult3 = mult(3);
auto comb1 = make_plus(add2, mult3);
auto comb2 = make_plus(mult(10), make_plus(add2, mult3));
这是一个为良好衡量标准添加minus
的程序。
#include <iostream>
struct add
{
add(double c): c_(c) {}
double operator()(double x) {
return c_ + x;
}
double c_;
};
struct mult
{
mult(double c): c_(c) {}
double operator()(double x) {
return c_ * x;
}
double c_;
};
template<typename T1, typename T2>
struct plus
{
plus(T1 t1, T2 t2) : t1_(t1), t2_(t2) {}
double operator()(double x)
{
return t1_(x) + t2_(x);
}
T1 t1_;
T2 t2_;
};
template<typename T1, typename T2>
plus<T1, T2> make_plus(T1 t1, T2 t2)
{
return plus<T1, T2>(t1, t2);
}
template<typename T1, typename T2>
struct minus
{
minus(T1 t1, T2 t2) : t1_(t1), t2_(t2) {}
double operator()(double x)
{
return t1_(x) - t2_(x);
}
T1 t1_;
T2 t2_;
};
template<typename T1, typename T2>
minus<T1, T2> make_minus(T1 t1, T2 t2)
{
return minus<T1, T2>(t1, t2);
}
int main()
{
add add2 = add(2);
mult mult3 = mult(3);
auto comb1 = make_plus(add2, mult3);
auto comb2 = make_plus(mult(10), make_plus(add2, mult3));
auto comb3 = make_minus(mult(10), make_plus(add2, mult3));
std::cout << comb1(10) << std::endl;
std::cout << comb2(10) << std::endl;
std::cout << comb3(10) << std::endl;
}
输出:
42
142
58
另一个选项是在特定于应用程序的命名空间中创建类型add
,mult
,plus
和minus
,然后添加operator+
和{{ 1}}重载使operator-
中的代码更直观。
main
答案 1 :(得分:1)
这是一个使用多态lambda(需要C ++ 14)的相当简洁的解决方案。为简短起见,此示例使用命名函数并仅支持一个函数参数。但是,使用运算符重载扩展此方法以支持多个参数和更自然的调用语法相当容易。
#include <type_traits>
struct arg_t {};
auto eval(auto const& x, arg_t) {
return x;
}
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
auto eval(auto const&, T const& t) {
return t;
}
template <typename F, std::enable_if_t<!std::is_arithmetic<F>::value, int> = 0>
auto eval(auto const& x, F const& f) {
return f(x);
}
auto binary(auto const& a, auto const& b, auto const& f) {
return [a, b, f](auto const& v) { return f(eval(v, a), eval(v, b)); };
}
auto sum(auto const& a, auto const& b) {
return binary(a, b, [](auto const& a, auto const& b) { return a + b; });
}
auto product(auto const& a, auto const& b) {
return binary(a, b, [](auto const& a, auto const& b) { return a * b; });
}
然后这样打电话:
#include <iostream>
int main() {
arg_t x;
auto f = sum(sum(x, 2), product(3, x));
std::cout << f(4) << "\n";
}