假设我想要一个C ++函数对两个输入执行算术运算,将它们视为给定类型:
伪:
function(var X,var Y,function OP)
{
if(something)
return OP<int>(X,Y);
else if(something else)
return OP<double>(X,Y);
else
return OP<string>(X,Y);
}
适合OP的函数可能如下:
template <class T> add(var X,var Y)
{
return (T)X + (T)Y; //X, Y are of a type with overloaded operators
}
所以,问题是函数的签名是什么样的?如果操作符函数是非模板化的,我可以这样做,但是我对这种额外的复杂性感到困惑。
答案 0 :(得分:6)
模板函数不能作为模板参数传递。在将此函数传递给另一个模板函数之前,必须手动推导此函数的模板参数。例如,你有功能
T sum(T a, T b)
{
return a + b;
}
您想将其传递给callFunc:
template<typename F, typename T>
T callFunc(T a, T b, F f)
{
return f(a, b);
}
你不能简单地写
int a = callFunc(1, 2, sum);
你必须写
int a = callFunc(1, 2, sum<int>);
为了能够在不编写 int 的情况下传递 sum ,您必须编写一个functor - struct或类,其中operator()将调用您的模板函数。然后,您可以将此仿函数作为模板参数传递。这是一个例子。
template<class T>
T sum(T a, T b)
{
return a + b;
}
template<class T>
struct Summator
{
T operator()(T a, T b)
{
return sum<T>(a, b);
}
};
template<template<typename> class TFunctor, class T>
T doSomething(T a, T b)
{
return TFunctor<T>()(a, b);
//Equivalent to this:
//TFunctor<T> functor;
//return functor(a, b);
}
int main()
{
int n1 = 1;
int n2 = 2;
int n3 = doSomething<Summator>(n1, n2); //n3 == 3
return 0;
}
答案 1 :(得分:5)
我有点困惑...为什么伪代码中的类型区别?
C ++模板允许对模板进行完全类型推导:
template <typename T, typename F>
T function(T x, T y, F op) {
return op(x, y);
}
这里,F
适合可以使用()
函数调用语法调用并且正好接受类型T
的两个参数(或者可以隐式转换为它)的任何(特别是函数)。
答案 2 :(得分:4)
你在找这个吗?
template<class T> T add(T X, T Y)
{
return X + Y;
}
或者您正在寻找一些类似添加的东西吗?
template<class T, class F>
T Apply(T x, T y, F f)
{
return f( x, y );
}
通过:
调用int x = Apply( 2, 4, add<int> );
答案 3 :(得分:2)
我使用lambdas。
auto add = [](const auto& lhs, const auto& rhs) {
static_assert(std::is_arithmetic<typename std::decay<decltype(lhs)>::type>::value,
"Needs to be arithmetic.");
static_assert(std::is_arithmetic<typename std::decay<decltype(rhs)>::type>::value,
"Needs to be arithmetic.");
return lhs + rhs;
};
template<typename LHS, typename RHS, typename FUNC
, typename OUT = typename std::result_of<FUNC(LHS, RHS)>::type>
constexpr OUT do_arithmetic(LHS lhs, RHS rhs, FUNC func) {
return func(lhs, rhs);
}
constexpr auto t = do_arithmetic(40, 2, add);
static_assert(t == 42, "Wrong answer!");
static_assert(std::is_same<std::decay<decltype(t)>::type, int>::value,
"Should be int.");
答案 4 :(得分:1)
我认为你正在寻找Strategy Pattern。
答案 5 :(得分:1)
FloatBuffer
答案 6 :(得分:0)
我不确定你问题中的这个var
是什么意思。它肯定不是一个有效的C ++关键字,所以我认为它类似于boost:any
。此外,该函数缺少结果类型。我添加了另一个var
,无论可能是什么。您的解决方案可能如下所示:
template< template<typename> class Func >
var function(var X, var Y, Func OP)
{
if(something)
return OP<int>(X,Y);
else if(something else)
return OP<double>(X,Y);
else
return OP<string>(X,Y);
}
有趣的模板参数本身就是一个模板,因此它的名称是“模板模板参数”。您传入模板的名称,而不是实例。也就是说,您传递的是std::plus
,而不是std::plus<int>
:
return function( a, b, std::plus );