4

I've created a template class which triggers a runtime text output whenever an instantiation of it occurs:

template<typename T>
struct verbose {
    verbose()
    {
        std::cout << "Instantation occured!" << std::endl;
    }
};

template<typename T>
struct base
{
    inline static verbose<T> v;
};

When I force to create instantiation, it shows an output:

template struct base<int>;
//output: Instantation occured!

(Check on Wandbox).

On the other hand, when I use it with a CRTP pattern, it seems that instantiation does not occur:

class test : public base<test>
{
};

(Check on Wandbox)

Is this behavior OK with the ISO standard? Can I somehow force to make instantiation, without requiring users of my template class (base) to write additional code? For me, the important thing is the side effect of the static variable constructor.

Mariusz Jaskółka
  • 4,137
  • 2
  • 21
  • 47
  • 2
    When you say "an instantiation", do you mean a template instantiation or creating an instance of an object? Because the code you've written does the latter, not the former. There's no way to get a message during template instantiation, because that's a compile-time process, not a runtime one. – Nicol Bolas Jan 09 '20 at 17:02
  • can't you get a message with static assert – Yamahari Jan 09 '20 at 17:05
  • 1
    @NicolBolas The intent is to get the message during program initialization, which works when explicitly instantiating the `base` but not when doing CRTP. See https://wandbox.org/permlink/yp5bGnsCTDcHMtrY. – Max Langhof Jan 09 '20 at 17:05
  • @NicolBolas I mean exactly template instantiation. Of course, it's a compile-time process, but it can trigger runtime code execution, as it does in the first example from Wandbox. – Mariusz Jaskółka Jan 09 '20 at 17:06
  • 2
    @Yamahari Not in a valid program. If you see a message from `static_assert`, your program is ill-formed. – Max Langhof Jan 09 '20 at 17:06
  • 1
    Odr use `v` (in destructor or constructor for example). – Jarod42 Jan 09 '20 at 17:15
  • @FrançoisAndrieux That is incorrect: https://wandbox.org/permlink/6A48EmnnfU0S9kXQ – Max Langhof Jan 09 '20 at 17:16
  • @FrançoisAndrieux Of course it's initialized in runtime, as cout always runs in runtime. The essential part of the question is: "without requiring users of my template class (base) to write additional code" (eg. making an object) – Mariusz Jaskółka Jan 09 '20 at 17:17
  • Does this answer your question? [How to force a static member to be initialized?](https://stackoverflow.com/questions/6420985/how-to-force-a-static-member-to-be-initialized) – Davis Herring Jan 10 '20 at 05:05

1 Answers1

4

Your CRTP usage falls under implicit instantiation:

When code refers to a template in context that requires a completely defined type, or when the completeness of the type affects the code, and this particular type has not been explicitly instantiated, implicit instantiation occurs. For example, when an object of this type is constructed, but not when a pointer to this type is constructed.

This applies to the members of the class template: unless the member is used in the program, it is not instantiated, and does not require a definition.
cppreference

Following the second paragraph, since base<test>::v is never actually used, no instantiation of base<test>::v actually occurs.

Since a usage is required to generate its instantiation, there will need to be additional code to get your desired output. For example, you could add a constructor to base:

template<typename T>
struct base
{
    inline static verbose<T> v;
    base() { (void)&v; }
};

This alone is not enough to trigger your output based on the definition of test by itself. However, if your program tries to create an object from test, then the formation of the constructor will cause the template's constructor to be used, and thus base<test>::v will be instantiated.

Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193
  • So, from your answer I assume I must require "users of my template class (base) to write additional code". Or just find another way how to allow my class users to be lazy ;) – Mariusz Jaskółka Jan 09 '20 at 18:55
  • If your class users actually try to create an object from `test`, then you can add something to `base<>` to get your output. Answer is updated. – jxh Jan 10 '20 at 16:25