Предположим, что у нас есть два типа (полный и неполный):
struct CompleteType{};
struct IncompleteType;
Также у нас есть код шаблона:
#include <type_traits>
template <typename = X(T)>
struct Test : std::false_type {};
template <>
struct Test<T> : std::true_type {};
T может быть CompleteType или IncompleteType здесь, а X(T) может быть T, decltype(T()) или decltype(T{}) (предположим, что X(T) - макрос).
Этот код используется следующим образом:
std::cout << std::boolalpha << Test<>::value << std::endl;
Ниже вы можете увидеть, как разные компиляторы имеют дело с таким кодом:
clang 3.4
X(T) \ T CompleteType IncompleteType
T true true
decltype(T()) true --- (1, 2)
decltype(T{}) true --- (1, 2)
-
error: invalid use of incomplete type 'IncompleteType'предоставляется даже в объявлениях классов классов с неполными типами (как дляdecltype(T()), так иdecltype(T{}), но не для простогоT) без использованияTest<>::valueв коде. -
error: too few template arguments for class template 'Test'
g++ 4.8.1
X(T) \ T CompleteType IncompleteType
T true true
decltype(T()) true true
decltype(T{}) true true
vС++ 18.00.21005.1
X(T) \ T CompleteType IncompleteType
T true true
decltype(T()) true --- (1)
decltype(T{}) true --- (2)
-
error C2514: 'IncompleteType' : class has no constructors -
error C2440: '<function-style-cast>' : cannot convert from 'initializer-list' to 'IncompleteType' Source or target has incomplete type
Какой компилятор действует в соответствии со стандартом? Обратите внимание, что простая строка типа std::cout << typeid(X(IncompleteType)).name() << std::endl; не компилируется для всех компиляторов для всех вариантов X (кроме vС++ и > X(T) == T).