将指针到模板函数作为函数参数传递?

时间:2009-08-15 21:37:58

标签: c++ templates operator-overloading

假设我想要一个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
}

所以,问题是函数的签名是什么样的?如果操作符函数是非模板化的,我可以这样做,但是我对这种额外的复杂性感到困惑。

7 个答案:

答案 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 );