I have some legacy code and I need to add a new class for the message (which is irrelevant to my question). But it turns out that I need to declare an empty constructor in o
C++14 [temp.inst]/2:
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.
This says clearly that Message<A>::test
will not be initialized unless it is used in a way that requires its definition to exist.
The only expression in your program that would require the definition is test.dummy()
in the constructor of Message<A>
; so if that expression is removed then test
must not be initialized.
For the case where test.dummy()
is present, note that it is inside a template function, the constructor of Message<A>
. If this constructor is never instantiated, then test.dummy()
will not be considered.
As pointed out by VTT, [class.ctor] says that the explicitly-defaulted constructor for A
means that no constructor is defined unless an A
is odr-used.
Your code doesn't odr-use an A
, therefore A
's constructor is not defined, therefore there is no invocation of base class constructor (which would only happen if if A
's constructor was defined), therefore the constructor template Message<A>()
is not instantiated, therefore test
is not required to exist.
If you leave A
constructor defaulted and never call it then there is no need to generate it and therefore no need to create test
. If you explicitly default it at definition, call A
constructor or access A::test
it will be initialized properly.
12.1 Constructors [class.ctor]
7 A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.
struct A : public Message<A>
{
A() = default; // no constructor is emitted unless A is instantiated
A(); // declaration
};
A::A() = default; // explicit default definition
int
main()
{
A a; // instantiation
A::test; // just explicitly access test so it is initialized regardless of A constructor
}