Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 588
xskxzr Avatar asked Sep 06 '18 09:09

xskxzr


People also ask

What is implicit instantiation?

Implicit instantiation means that the compiler automatically generates the concrete function or class for the provided template arguments. In general, the compiler also deduces the template arguments from the function's arguments. In C++17, the compiler can also deduce the template arguments for class templates.

Under what circumstances will C++ instantiate a generic function implicitly?

Unless a template specialization has been explicitly instantiated or explicitly specialized, the compiler will generate a specialization for the template only when it needs the definition. This is called implicit instantiation.


1 Answers

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.

like image 89
StoryTeller - Unslander Monica Avatar answered Oct 14 '22 01:10

StoryTeller - Unslander Monica