Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parameter type is treated as complete by the compiler, but its definition isn't yet visible

Assume I have the following code snippet:

template <class T>
class Bar
{
    // static_assert(sizeof(T) > 0); // (1)
public:
    void method()
    {
        static_assert(sizeof(T) > 0); // (2)
    }
};

class Foo; // (3)

template class Bar<Foo>; // (4)

class Foo{}; // (5)

If we uncomment the line (1), we get a compile-time error "incomplete type T", and it seems to be clear: class Bar instantiation is launched by (4), and at that point class Foo is only forward-declared by (3) and not yet defined by (5).

But if the line (1) is commented out, then this code compiles with no errors, and it confuses me: (4) is an explicit template instantiation definition and it forces the compiler to generate void method() code, and line (2) should also generate the same error, since the definition of Foo is made later in (5).

What do I miss, why does the code from the snippet compiles?

UPDATE: Code compiles under GCC 8.2.0 and MSVC 19.16.27025.1, but under Clang 7.0.0 it gives an "incomplete type" error.

like image 590
undermind Avatar asked Jan 01 '19 17:01

undermind


1 Answers

As per the standard goes, during implicit instantiation only the declaration of member functions are instantiated but not their definition.

[temp.inst]/2 - The implicit instantiation of a class template specialization causes

  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...

but it doesn't say the same about explicit instantiations. The whole class is instantiated which means that it instantiates the definition of method() and at that point Foo isn't complete.

[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.

clang rejects the code.

like image 181
Jans Avatar answered Sep 22 '22 01:09

Jans