2016-10-23 2 views
0

В чем причина того, что в следующем примере экземпляр с тремя int работает со вторым шаблоном функции, но не с первым. Дополнительно: с типами State1/State1 он не работает.Ошибка рекурсивной вариации шаблонных шаблонов

struct State1{}; 
struct State2{}; 

#if 0 
template<typename none = void> 
constexpr void f() 
{ 
} 
template<typename First, typename... Rest> 
constexpr void f() 
{ 
    f<Rest...>(); 
} 
#else 
template<typename none = void> 
constexpr void f() 
{ 
} 
template<int First, int... Rest> 
constexpr void f() 
{ 
    f<Rest...>(); 
} 
#endif 
void test() 
{ 
    f<1, 2, 3>(); 
// f<State1, State2>(); 
} 

Благодарим за любые советы!

+0

«Это не работает» не является проблемой. – melpomene

+0

'1' не является типом, и наоборот. – krzaq

+0

Один шаблон ожидает тип, вы его подаете целым литералом. В другом шаблоне ожидается целое число, которое вы подаете ему. Как вы удивлены, что это не работает? – DeiDei

ответ

0

Проблема в первом случае заключается в том, что оба шаблонных специализаций совпадают, когда вы передаете один параметр шаблона (пакет параметров может быть пустым), поэтому набор перегрузки содержит более одного кандидата. Вы можете использовать SFINAE, чтобы второй экземпляр не выполнялся:

#include <type_traits> 

struct State1{}; 
struct State2{}; 

template<typename none = void> 
constexpr auto f() -> void 
{ 
} 

template<typename First, typename... Rest> 
constexpr auto f() -> std::enable_if<sizeof...(Rest), void>::type 
    // This will not instantiate when the parameter pack is empty 
    // And the overload set will contain only the candidate above 
{ 
    f<Rest...>(); 
} 

int main() 
{ 
    f<State1, State2>(); 

    return 0; 
} 
Смежные вопросы