34

Can a template class in C++ have static members? Since it doesn't exist and is imcomplete before it is used, is this possible?

Community
  • 1
  • 1
rubixibuc
  • 7,111
  • 18
  • 59
  • 98
  • Your question is not clear. Here is the template class that has static members: http://www.codeproject.com/KB/cpp/value_t.aspx Afloat since 2004. – c-smile Apr 29 '11 at 04:47
  • C++ experts prefer the term "class template", because a class template is a template, not a class. That helps sidestep the "It doesn't exist" assumption made above. The class template obviously exists. It just hasn't got any instantiations yet, and it's those template instantiations that can have members. – MSalters Apr 29 '11 at 07:26
  • As an extension to this, and to @Potatoswatter's answer, what changes if I want to declare `static T foo;` in my class template? In the use case I'm considering, the set of types that will be used are fairly limited, it's guaranteed they'll all be basic POD types, e.g. `int`, `float`, `uint64_t` etc.etc.etc. Can I just create all the static member declarationsI think I'll need, and if necessary add more if a new type is used as the template type, leading to an undefined reference? – dgnuff Jun 13 '19 at 17:59

1 Answers1

42

Yes. The static member is declared or defined inside the template< … > class { … } block. If it is declared but not defined, then there must be another declaration which provides the definition of the member.

template< typename T >
class has_static {
    // inline method definition: provides the body of the function.
    static void meh() {}

    // method declaration: definition with the body must appear later
    static void fuh();

    // definition of a data member (i.e., declaration with initializer)
    // only allowed for const integral members
    static int const guh = 3;

    // declaration of data member, definition must appear later,
    // even if there is no initializer.
    static float pud;
};

// provide definitions for items not defined in class{}
// these still go in the header file

// this function is also inline, because it is a template
template< typename T >
void has_static<T>::fuh() {}

/* The only way to templatize a (non-function) object is to make it a static
   data member of a class. This declaration takes the form of a template yet
   defines a global variable, which is a bit special. */
template< typename T >
float has_static<T>::pud = 1.5f; // initializer is optional

A separate static member is created for each parameterization of the template. It is not possible to have a single member shared across all classes generated by the template. For that, you must define another object outside the template. A partially-specialized traits class might help with that.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • I am not sure, what you mean with the comments: "const integral types can be defined" and "other types cannot". What this implies for me, is that static members need to be const, but this is not the case. One use case of non-const integral members is the CRTP counter implementation given [here](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Object_counter). – LiKao Apr 29 '11 at 07:15
  • 1
    @LiKao: A const integral type may be defined (not merely declared) inside braces of the class block. Other types must be declared inside the braces and later defined at namespace scope. – Potatoswatter Apr 29 '11 at 07:56
  • @LiKao: expanded on the comments a bit. – Potatoswatter Apr 29 '11 at 08:10
  • 1
    I should have asked this before, but how are they invoked? – rubixibuc Apr 16 '12 at 06:43
  • @rubixibuc How are what invoked? – Potatoswatter Apr 17 '12 at 02:46
  • The static methods of template class and the static fields. Must you instantiate it somehow first or use a special syntax? – rubixibuc Apr 18 '12 at 00:41
  • @rubixibuc They are instantiated when you use them, just like nonstatic methods. Likewise, the declaration must be valid in any case, it's only the initialization (analogous to the function body) which is deferred until use of the member. For static data members, the special syntax is the declaration at namespace scope, outside the `class` block, which must appear in exactly one translation unit (not a header). – Potatoswatter Apr 18 '12 at 01:34
  • 1
    Could you please extend this answer to show how you write if you want to instantiate a static member function for a specific type in a cpp file that includes this header file? – HelloGoodbye Apr 16 '13 at 07:01
  • 2
    For anyone that visits this thread later, one instantiates the function `fuh` by writing `has_static::fuh()` (or with any other type in the place of `int`, since this class doesn't really use the `int`). – tomsmeding Oct 23 '14 at 13:05
  • @Potatoswatter ***It is not possible to have a single member shared across all classes generated by the template. For that, you must define another object outside the template. A partially-specialized traits class might help with that.*** Could you please explain that in more detail? – John Sep 09 '22 at 07:11