如果专业化已经被隐式实例化了,它是否被隐式实例化?

时间:2018-09-06 09:39:21

标签: c++ templates language-lawyer template-instantiation implicit-instantiation

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

#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

此代码compiles with GCC and Clang

根据[temp.inst]/1

  

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

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

然后,在X定义之后,#1暗示X<char>不再被实例化(仍然不完整),而#2暗示X<char>确实是再次实例化(成为完整类型)。

如果某个专门化已经被隐式实例化,它是否被隐式实例化?为什么#1#2之间有区别?

欢迎对标准进行解释。

1 个答案:

答案 0 :(得分:4)

  

如果某个专业化已经被隐式实例化,那么它是否被隐式实例化?

不。根据{{​​3}}:

  

类模板的专门化在翻译单元中最多具有一个实例化点。

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

  

功能模板,成员功能模板,   或类模板的成员函数或静态数据成员的   在翻译单元中有多个实例化点,并且   除上述实例化点外,对于任何   这样的专业化在内部具有实例化点   翻译单元,翻译单元的末尾也被认为是   实例化点。 [...]如果两个不同的实例化点根据一个定义规则赋予模板专业化不同的含义,则程序格式错误,无需诊断。

is_complete_helper::test是一个成员函数模板,其成员声明在静态断言之前被实例化。因此,它还必须在TU的末尾具有实例化。在哪里可能会给出不同的结果。因此,此特征取决于不良的NDR构造。