views:

449

answers:

4

Say I want a C++ function to perform arithmetic on two inputs, treating them as a given type:

pseudo:

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);
}

functions that fit OP might be like:

template <class T> add(var X,var Y)
{
 return (T)X + (T)Y; //X, Y are of a type with overloaded operators
}

So, the question is what would the signature for function look like? If the operator functions are non-templated I can do it, but I get confused with this extra complexity.

+2  A: 

Are you looking for this?

template<class T> T add(T X, T Y)
{
    return X + Y;
}

Or are you looking for something that calls something like add?

template<class T, class F>
T Apply(T x, T y, F f)
{
    return f( x, y );
}

Called via:

int x = Apply( 2, 4, add<int> );
Charles Bailey
+4  A: 

I'm a bit confused … why the type differentiation in your pseudo-code?

C++ templates allow full type deduction on templates:

template <typename T, typename F>
T function(T x, T y, F op) {
    return op(x, y);
}

Here, F fits anything (especially functions) that may be called with the () function call syntax and accepting exactly two arguments of type T (or implicitly convertible to it).

Konrad Rudolph
I think this is what I meant, didn't think of a function as a template argument.
John
+1  A: 

I think you're looking for the Strategy Pattern.

rlbond
+1  A: 

I'm not sure what this var thing in your question means. It's certainly not a valid C++ keyword, so I assume it's a type akin to boost:any. Also, the function is missing a result type. I added another var, whatever that might be. The your solution could look like this:

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);
}

The funny template argument is a template itself, hence its name "template template argument". You pass in the name of a template, not an instance. That is, you pass std::plus, not std::plus<int>:

return function( a, b, std::plus );
sbi