2016-07-16 3 views
0
#include <type_traits> 

template<typename T> 
T f(T&& a, T&& b) 
{ 
    return a + b; 
} 

template<typename T, typename... Args> 
T f(T&& a, T&& b, Args&&... args) 
{ 
    return f(a, f(b, std::forward<Args>(args)...)); 
} 

int main() 
{ 
    f(1, 2, 3); 
} 

VS 2015 Выходы: ошибка C2672: 'F': нет соответствия перегруженная функция не найденоПочему рекурсивные вариационные шаблоны не работают должным образом?

Почему это не работает, как ожидалось?

+0

Какой из звонков 'f' вы возникли проблемы с? В коде, который вы показываете, есть три. –

+2

в качестве подсказки g ++ 4.9.3 дает следующую ошибку: test.cpp: 10: 3: примечание: сбой аргумента шаблона/замещения: test.cpp: 12: 49: note: выведенные конфликтующие типы для параметра 'T' ('int &' и 'int') return f (a, f (b, std: forward (args) ...)); – robal

+2

std :: forward определяется в не robal

ответ

5

Проблема заключается в том, что вы не пересылает a или b при рекурсивном вызове f, что приводит к попытке вызвать перегрузку бинарного с a : int и b : int&. Вот первый шаг:

template<typename T> 
T f(T&& a, T&& b) { 
    return a + b; 
} 

template<typename T, typename... Args> 
T f(T&& a, T&& b, Args&&... args) { 
    return f(std::forward<T>(a), f(std::forward<T>(b), std::forward<Args>(args)...)); 
} 

Теперь проблема заключается в том, что все аргументы, переданные в должны иметь такую ​​же категорию стоимость и любой Lvalue аргумент вызовет ошибку, например, int i = 2; f(1, i, 3); не удастся. Чтобы исправить это ..:

template<typename T, typename U> 
typename std::decay<T>::type 
f(T&& a, U&& b) { 
    return a + b; 
} 

template<typename T, typename U, typename... Args> 
typename std::decay<T>::type 
f(T&& a, U&& b, Args&&... args) { 
    return f(std::forward<T>(a), f(std::forward<U>(b), std::forward<Args>(args)...)); 
} 

, который затем может быть упрощена:

template<typename T, typename U> 
typename std::decay<T>::type 
f(T&& a, U&& b) { 
    return a + b; 
} 

template<typename T, typename... Args> 
typename std::decay<T>::type 
f(T&& a, Args&&... args) { 
    return f(std::forward<T>(a), f(std::forward<Args>(args)...)); 
} 
+0

Лучше использовать авто как возвращаемый тип. decay не заботится о U. Добавление int для float (в этом порядке) должно возвращать float, а не int. –

+0

@EmilioGaravaglia: OP хотел, чтобы все типы были одинаковыми, поэтому в моем ответе не бережно относиться к поддержке разных типов. Существует несколько подходов к этому, но заданный вопрос помечен 'C++ 11', просто делая возвращаемый тип' auto' не является одним из них. : - [ – ildjarn

+0

да ... к сожалению, большая миссия от C++ 0x/1x specs. –

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