Reputation: 463
I'm trying to learn about boost mpl and I was wondering if something like this would be possible. Specifically, is it possible to conditionally typedef a function based on a template parameter? Something along the lines of this toy example:
template<typename arg1, typename arg2, typename rtype>
rtype getValue()
{
typedef boost::conditional<
// typedef boost::mpl::if_<
boost::is_same<rtype, double>,
double multiply(double a, double b),
int multiply(int a, int b)
> function;
function test;
return test(arg1::value, arg2::value);
}
I tried the above code and got the error that "template argument 2 is invalid". So I was wondering if there is a way to turn the function definition into a valid type since it is a valid typedef?
I am also aware there are many other ways to do this. I don't want a work around since this is an attempt to learn.
Upvotes: 1
Views: 261
Reputation: 153820
Functions are no types. You can write a typedef
with a function but that's just creating a type alias not the function type. For actual functions you could create a template using a function pointer as template argument and turn the function into a type this way. For example
template <typename T, T(*fun)(T, T)>
struct arithmetic_fun {
T operator(T x, T y) const { return fun(x, y); }
};
template <typename T>
T multiply(T x, T y) {
return x * y;
};
using int_multiply = arithmetic_fun<int, &multiply<int>>;
// ...
Using this approach is kind of unnecessary, though, as the standard C++ library contains class templates for the common arithmetic operations anyway. Of course, you could just use these making all this meta-programming moot to start with:
template <typename A1, typenam A2, typename R>
R getValue() {
using function = std::multiplies<R>;
function test;
return test(A1::value, A2::value);
}
Upvotes: 1
Reputation: 754
A typedef applies to types a function is not a type.
A function may have a type, for example, double multiply(double, double) has the type double (*)(double, double). However, the type is not actually linked to the function: double add(double, double) has the same type as double multiply(double, double).
What you may be able to do is create a functor, which is a class (a type) that can act like a function.
For example, something like:
class DoubleMultiplier
{
public:
double operator()(double value1, double value2) const
{
return value1 * value2;
}
};
class IntMultiplier
{
public:
int operator()(int value1, int value2) const
{
return value1 * value2;
}
};
template<typename arg1, typename arg2, typename rtype>
rtype getValue()
{
typedef boost::conditional<
// typedef boost::mpl::if_<
boost::is_same<rtype, double>,
DoubleMultiplier,
IntMultiplier
> function;
function test;
return test(arg1::value, arg2::value);
}
I'm assuming your specific example is a simplified version of something more complex. DoubleMultiplier and IntMultiplier do the same thing so you could make a templated Multiplier instead -- of course you could also just multiply arg1::value1 by arg2::value2 directly in getValue().
Upvotes: 2