joshu
joshu

Reputation: 463

Conditional typedef of a function

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

Answers (2)

Dietmar K&#252;hl
Dietmar K&#252;hl

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

Steven
Steven

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

Related Questions