Why some expression that looks like a definition for normal types unexpectedly turns out to be a declaration for templates?

Viewed 54

These expressions are all definitions for normal types:

int num;
bool flag;

But some expression that looks like a definition for normal types unexpectedly turns out to be a declaration for templates(for details, see below and https://ibb.co/k0qCHp2)!

Here is the related code snippet(https://godbolt.org/z/a9W9Wc):

    #include<iostream>
    template<typename T>
    class Test
    {
    public:
        static constexpr int sdm = T(nullptr);
        static int f(void){static_assert(sizeof(T)==0);}
        int g(void){static_assert(sizeof(T)==0);}
    };
    
    int main()
    {
       Test<int> intTest;  //**O'DWYER says that it's a declaration instead of a definition in his talk(see https://ibb.co/k0qCHp2)! Why?** 
       //But I can get this object's address indeed.
       std::cout << &intTest << std::endl;
    }

If Test<int> intTest; is a declaration, I can draw the conclusion that std::vector<int> vec; and std::map<std::string, int> map are both declarations too. Am I right?

1 Answers

Test<int> intTest; is a definition (which is also a declaration; all definitions are also declarations) of the variable intTest. However, this fact is rather irrelevant to your implied question of "why does this line compile". The reason it compiles is this: it causes an implicit instantiation of the class template specialization Test<int>, but not of its member functions and static data members.

[temp.inst]/2 The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, member classes, scoped member enumerations, static data members, member templates, and friends...

[temp.inst]/9 An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement (9.4.1), unless such instantiation is required...

Those member functions and static data members will be implicitly instantiated when they themselves are used; it is at this point that the compiler will discover their definition is ill-formed, and issue appropriate diagnostic.

[temp.inst]/3 Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

Related