10

标题中的问题已经很清楚了。更具体地说,请考虑以下示例:

#include <type_traits>

template <typename T>
struct is_complete_helper {
    template <typename U>
    static auto test(U*)  -> std::integral_constant<bool, sizeof(U) == sizeof(U)>;
    static auto test(...) -> std::false_type;
    using type = decltype(test((T*)0));
};

template <typename T>
struct is_complete : is_complete_helper<T>::type {};

// The above is an implementation of is_complete from https://stackoverflow.com/a/21121104/5376789

template<class T> class X;

static_assert(!is_complete<X<char>>::type{}); 
// X<char> should be implicitly instantiated here, an incomplete type

template<class T> class X {};

static_assert(!is_complete<X<char>>::type{}); // #1

X<char> ch; // #2

此代码使用 GCC 和 Clang 编译

根据[temp.inst]/1

除非类模板特化已被显式实例化或显式特化,否则当在需要完全定义的对象类型的上下文中引用该特化或当类类型的完整性影响程序的语义时,类模板特化将被隐式实例化.

X<char>由于 被隐式实例化static_assert(!is_complete<X<char>>::type{}),这会生成不完整的类型。

然后,在 , 的定义之后X#1表明X<char>没有再次实例化(仍然不完整),而#2表明X<char>确实再次实例化(成为完整类型)。

如果特化已经被隐式实例化,它是否会被隐式实例化?#1为什么和之间有区别#2

欢迎对标准进行解释。

4

1 回答 1

4

如果特化已经被隐式实例化,它是否会被隐式实例化?

不,根据[temp.point]/8

类模板的特化在翻译单元内最多有一个实例化点。

x<char>只需要实例化一次,而不是在第一个静态断言中命名时,仅在ch. 但是, [temp.point]/8 也说

函数模板、成员函数模板或类模板的成员函数或静态数据成员的特化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于任何此类在翻译单元内有一个实例化点的特化,翻译单元的末端也被认为是一个实例化点。[...] 如果两个不同的实例化点根据单一定义规则赋予模板特化不同的含义,则程序格式错误,不需要诊断。

Andis_complete_helper::test 一个成员函数模板,其声明在静态断言之前被实例化。所以它还必须在 TU 结束时有一个实例化。它可能会给出不同的结果。因此,此特征取决于格式错误的 NDR 构造。

于 2018-09-06T09:56:03.307 回答