Is a specialization implicitly instantiated if it has already been implicitly instantiated?

谁说我不能喝 提交于 2019-12-10 02:02:31

问题


The question in the title is clear enough. To be more specific, consider the following example:

#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

This code compiles with GCC and Clang.

According to [temp.inst]/1:

Unless a class template specialization has been explicitly instantiated or explicitly specialized, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.

X<char> is implicitly instantiated due to static_assert(!is_complete<X<char>>::type{}), which generates an incomplete type.

Then, after the definition of X, #1 suggests that X<char> is not instantiated again (still incomplete) while #2 suggests that X<char> is indeed instantiated again (becomes a complete type).

Is a specialization implicitly instantiated if it has already been implicitly instantiated? Why is there a difference between #1 and #2?

An interpretation from the standard is welcome.


回答1:


Is a specialization implicitly instantiated if it has already been implicitly instantiated?

No. According to [temp.point]/8:

A specialization for a class template has at most one point of instantiation within a translation unit.

x<char> need only be instantiated once, and it's not when it's named in the first static assertion, only before ch. But, [temp.point]/8 also says

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. [...] 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.

And is_complete_helper::test is a member function template whose declaration is instantiated before the static assertion. So it must also have an instantiation at the end of the TU. Where it will likely give a different result. So this trait is depending on an ill-formed NDR construct.



来源:https://stackoverflow.com/questions/52201121/is-a-specialization-implicitly-instantiated-if-it-has-already-been-implicitly-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!