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

1

6

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.

Springspringboard answered 1/1, 2019 at 17:50 Comment(2)
Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.Unfrock
@Unfrock Thanks, I added description. It turns out that clang doesn't compile this.Springspringboard
B
7

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.

Buffington answered 1/1, 2019 at 18:24 Comment(1)
Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?Springspringboard

© 2022 - 2024 — McMap. All rights reserved.