Consider the following code:
#include <iostream>
struct M {
M() { std::cout << "M\n"; }
};
template <class T>
struct Test {
Test() { std::cout << "Test\n"; }
inline static auto m = M{};
};
int main() {
Test<int> t1;
//Test t;
//(void)&t1.m;
}
Using the latest GCC or Clang the only "Test" is printed out. But if we use an address of m
object (uncomment the last line (void)&t1.m;
) or transform Test
class template into the regular (non-templated) class then the M
constructor was called.
Is this behaviour allowed by the C++ standard? Any quotes?
Yes, it's spelled out in the standard.
[temp.inst] (emphasis mine)
4 Unless a member of a class template or a member template is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or if the existence of the definition of the member affects the semantics of the program; 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.
Since your example doesn't use the static data member at all, its definition is never fully instantiated.