2016-06-17 3 views
1

Я пытаюсь узнать о boost mpl, и мне было интересно, возможно ли что-то подобное. В частности, возможно ли условно typedef функцию, основанную на параметре шаблона? Что-то вдоль линий этого игрушечного например:Условный typedef функции

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

Я попытался выше код и получил ошибку, что «аргумент шаблона 2 недействителен». Поэтому мне было интересно, есть ли способ превратить определение функции в допустимый тип, поскольку он является допустимым typedef?

Я также знаю, что есть много других способов сделать это. Я не хочу работать, потому что это попытка учиться.

+0

Вам не хватает запятой после is_same <>? – lorro

+0

@lorro Я, код, который я пытаюсь скомпилировать, к сожалению. – joshu

ответ

2

typedef относится к типам функция не является типом.

Функция имеет тип, например, двойной умножить (двойной, двойной) имеет тип double (*) (двойной, двойной). Однако тип фактически не связан с функцией: double add (double, double) имеет тот же тип, что и double multiply (double, double).

Что вы можете сделать, это создать functor, который является классом (типом), который может действовать как функция.

Например, что-то вроде:

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

Я предполагаю, что ваш конкретный пример представляет собой упрощенную версию чего-то более сложного. DoubleMultiplier и IntMultiplier делают то же самое, чтобы вместо этого вы могли использовать шаблонный множитель - конечно, вы могли бы просто просто умножить arg1 :: value1 на arg2 :: value2 непосредственно в getValue().

1

Функции отсутствуют. Вы можете написать typedef с функцией, но это просто создание псевдонима типа, а не типа функции. Для реальных функций вы можете создать шаблон с помощью указателя функции в качестве аргумента шаблона и таким образом превратить функцию в тип. Например

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>>; 
// ... 

Используя этот подход является своего рода ненужным, хотя, как стандартная библиотека C++ содержит шаблоны классов для общих арифметических операций в любом случае. Конечно, вы можете просто использовать их, чтобы начать все это метапрограммирование:

template <typename A1, typenam A2, typename R> 
    R getValue() { 
     using function = std::multiplies<R>; 
     function test; 
     return test(A1::value, A2::value); 
    }