根据实例化点期望不同的类型

Expecting different types depending of point of instantiation

我希望以下内容是格式错误的 NDR,但似乎不是:-(

#include <type_traits>

template <typename T, typename Enabler = void>
struct is_complete : std::false_type {};

template <typename T>
struct is_complete<T, std::void_t<decltype(sizeof(T) != 0)>> : std::true_type {};

class X;

static_assert(!is_complete<X>::type{}); // incomplete type

class X {};

static_assert(!is_complete<X>::type{}); // complete, but already instantiated

Demo

注意:假设 sizeof(T) != 0 对完整性特征有效(因为没有类型可以有 sizeof(T) == 0,使用其他常量会强制找到更好的名称对于特征 :-) )

它是 Is a specialization implicitly instantiated if it has already been implicitly instantiated? 代码的变体,其中程序已被声明为格式错误的程序,不需要诊断 (NDR),作为 方法 is_complete_helper<X>::test<X> 有两种不同的含义,具体取决于实例化点。

似乎使程序格式错误的引用,但据我所知并非如此:

the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template.

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

我错了?或者不幸的是这个程序是正确的。

I expect the following to be ill formed NDR, but it seems not :-(

你不能用程序编译(和运行)的事实作为它不是错误格式的证据,NDR。就像您不能使用看似有效的程序输出来证明它没有表现出未定义的行为一样。

也就是说,这里的相关规则是[temp.point]/8:

A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

我们只有 is_complete<X> 的一个实例化点:就在第一个 static_assert 之前。所以,这是 "fine" - 它可以说是令人困惑和糟糕的,但它的格式是正确的。

但是,但是,如果我们将其拆分:

// a.cpp
struct X;
static_assert(!is_complete<X>::value);

// b.cpp
struct X { };
static_assert(is_complete<X>::value);

现在这是错误的格式,不需要诊断。


注意,您不需要 sizeof(T) != 0。只需 sizeof(T) 即可。您不能采用不完整类型的 sizeof,因此您只需要检查 sizeof(T) 是否为有效表达式。