2012-06-19 3 views
6

Информация:Возврат типа функции шаблона

В настоящее время я пытаюсь узнать шаблон метапрограммирования (следуя this book). Один из полезных примеров, которые они дают, - это анализ размеров. Я реализовал его, как в книге, и все было в порядке; see here.

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

У меня есть 3-вектор класс, который имеет все необходимые операции для умножения/деления на скаляры и т.д., так что я хотел бы сделать что-то вроде

quantity<double,mass> m(1.0); 
quantity<vect,acceleration> a(vect(0.0,0.0,-9.81)); 
quantity<vect,force> f = m*a; 

Первая попытка:

Чтобы добиться этого, я попытался использовать примеры из книги, чтобы обрабатывать два разных типа в качестве входных данных для operator* и operator/, однако я ударил стену, когда дело доходит до типа возврата.

Я знаю, что здесь возвращаемый тип double * vect является vect, но если они наоборот vect * double это еще vect. Хуже; в принципе тип возврата может быть любым. Поэтому я хочу способ продлить operator* на что-то вроде

template<class T1, class T2, class Dim1, class Dim2> 
quantity<X, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2) 
{ 
    return quantity<X, 
        typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
        (q1.value()*q2.value()); 
} 

где X является тип возвращаемого q1.value()*q2.value() и выводится во время компиляции. Я попробовал просто добавить еще один шаблонный класс T3 к подписи и вернуть его T3, но, похоже, он не может определить, что должно быть T3.

Вторая попытка:

Далее я попытался использовать decltype следующим

template<class T1, class T2> 
struct return_type 
{ 
    auto mult_f(const T1& a, const T2& b)->decltype(a*b){return a*b;} 
    typedef decltype(mult_f) type; 
}; 

template<class T1, class T2, class Dim1, class Dim2> 
quantity<typename return_type<T1,T2>::type, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2) 
{ 
    return quantity<typename return_type<T1,T2>::type, 
        typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type> 
        (q1.value()*q2.value()); 
} 

Однако это бросает множество непонятных ошибок компилятора.

Вопрос:

Мой вопрос тогда, я использую decltype в правильном пути, но не хватает какой-то синтаксис, например, a typename спецификатор где-нибудь? Или; возможно ли это сделать так, и если нет, то как можно вычислить возвращаемый тип функции?

Спасибо.

ответ

6

Итак, первый тип return_type<T1,T2>::type не то, что вы, кажется, ожидает, но это тип метода, а именно T3 (return_type::*)(const T1&, const T2&) с T3 быть типа вы ожидаете.Если вы хотите использовать промежуточный класс, вы можете использовать:

template <typename T1, typename T2> 
struct return_type 
{ 
    typedef decltype(std::declval<T1>()*std::declval<T2>()) type; 
}; 

Но вы можете также использовать непосредственно decltype(T1()*T2()) получить тип продукта.

Редактировать: Я редактировал код с предложением ildjarn, поэтому нет необходимости в конструктивных типах по умолчанию. Просто не забудьте включить <utility>

+0

Да, я могу сказать из вывода компилятора, что получаю целую подпись функции. Я не знаю, почему я так много усложнял, ваш пример компилируется отлично :) Требование конструктора по умолчанию для меня здесь не проблема. – Dan

+2

@ Dan: обратите внимание, что книга была написана до появления C++ 11 и 'decltype' /' auto', что сделало вещи ** намного сложнее. –

+2

Заменить 'decltype (T1() * T2())' с 'decltype (std :: declval () * std :: declval ())', и вы больше не требуете конструктивности по умолчанию. – ildjarn

Смежные вопросы