10
votes

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
IIRC, this breaks the odr.YSC
@YSC Do you mean #1 and #2 break the odr? But it is so common that a specialization is referred to multiple times...xskxzr
I was wrong, it would have break the odr if multiple TU were involed, as per [temp.point]/8.YSC
I think the program is ill formed NDR as is_complete<X<char>>::type depends of instantiation point (including EOF one).Jarod42
@Jarod42 - The EOF one is only for functions. Classes have only a single POI.StoryTeller - Unslander Monica

1 Answers

4
votes

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.