2015-01-02 2 views
0

Если USE_STATIC_ASSERT is 0, это работает как ожидается (получение индексированного типа из списка). Если 1 static_assert() всегда срабатывает. Я бы подумал, что static_assert() произойдет, только если все typename с исчерпаны. Почему это не так?Почему «static_assert» всегда вызывается?

#define USE_STATIC_ASSERT 1 
template <unsigned int I, typename ...Ts> 
struct items; 

template <typename T, typename ...Ts> 
struct items<0, T, Ts...> 
{ 
    typedef T type; 
}; 

template <unsigned int I, typename T, typename ...Ts> 
struct items<I, T, Ts...> : items<I-1, Ts...> 
{ 
}; 

#if USE_STATIC_ASSERT 
template <unsigned int I> 
struct items<I> 
{ 
    static_assert(false, "Ran out of Ts."); 
}; 
#endif 


int main() 
{ 
    cout << is_same<float, items<1, int, float, double>::type>::value << endl; 
} 

ответ

5

Даже если частичная специализация items, которая содержит static_assert не экземпляр, компилятор имеет право отклонить этот код в соответствии с §14.6 [temp.res]/П8:

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

Чтобы обойти это, вы можете сделать выражение в static_assert зависит от другого шаблона класса:

#include <type_traits> 

template <unsigned int I> 
struct AlwaysFalse : std::false_type {}; 

template <unsigned int I> 
struct items<I> 
{ 
    static_assert(AlwaysFalse<I>{}, "Ran out of Ts."); 
    //   ~~~~~~~~~~~~~~~^ 
}; 
Смежные вопросы