Предположим, что у нас есть два типа (полный и неполный):
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
).