0

There is a similar question here but it's related to templates with the typename keyword.

Given a template:

template < int X, char Y >
struct foo
{
    char myArray[ X <= 0 ? 1 : X ];
    static const char Z = Y;
}

Would that static member be shared between all instances of foo or will the compiler see that the template has been called with different arguments and create a new type?

Community
  • 1
  • 1
Twifty
  • 3,267
  • 1
  • 29
  • 54
  • Your linked question answers this. It creates a new class for every different argument. – Rapptz Jul 17 '13 at 02:14
  • What's with the downvotes? A valid question in my opinion. My compiler shows struct foo as being of type foo, in my mind all such types are the same and should share the static member. – Twifty Jul 17 '13 at 02:19
  • 1
    How could a `foo<0,'a'>` be the same type as a `foo<999,'b'>`? The `foo<999,'b'>` type would have to be a different size if nothing else. And what do you mean by "my compiler shows `struct foo` as being of type `foo`"? If you mean that's how it shows up in the debugger, then that's a limitation of the debugger or debug symbols. – Michael Burr Jul 17 '13 at 02:30
  • Think of a template as simply being a recipe that tells the compiler how to build a class or function (or variable in C++14) from some parameters. Once those classes/functions/variables are built, they are just like any other class/function/variable. So `class foo<0,'a'>` is completely distinct from `class foo<1,'a'>` just as `class A` and `class B` are. – Casey Jul 17 '13 at 04:25

2 Answers2

3

The static constant member assigned there changes depending on the value that is being passed by the template parameter. Shorten it to something like this:

template<int X>
struct foo { 
    static const int value = X;
};

You wouldn't expect foo<10>::value to be equal to foo<11>::value would you? This is commonly used in template meta programming because the value of that static constant depends on a template parameter.

Rapptz
  • 20,807
  • 5
  • 72
  • 86
3

Indeed the template parameters you defined are non-type parameters, as opposed to the two other varieties of template parameters: type-parameters and template-parameters.

However, they are still template parameters, and you will get an entirely new data type for each distinct set of template arguments. For example, foo<3,'a'> is a different data type from foo<4,'a'>, which again is different from foo<3,'b'> and so forth.

Hence, the static members are separately allocated and initialized for each choice of template arguments, too.

In this respect, non-type parameters, type-parameters and template-parameters all work the same way.


For reference, from the Standard (C++11):

(§14.7/6) Each class template specialization instantiated from a template has its own copy of any static members. [ Example:

template<class T> class X {
  static T s;
};
template<class T> T X<T>::s = 0;
X<int> aa;
X<char*> bb;

X<int> has a static member s of type int, and X<char*> has a static member s of type char*. — end example ]

The example given by the Standard above refers to type-parameters, but section 14.7/6 is part of a general discussion of templates. The broader context makes it clear that this holds for templates that use non-type parameters (or a combination of type-, non-type- and template-parameters).

There is also a section on type-equivalence for template instantiations, which explains under what circumstances template instantiations with non-type parameters are considered as equal (relevant parts emphasized by me):

(§14/1) Two template-ids refer to the same class or function if
— their template-names, operator-function-ids, or literal-operator-ids refer to the same template and
— their corresponding type template-arguments are the same type and
— their corresponding non-type template arguments of integral or enumeration type have identical values and
— their corresponding non-type template-arguments of pointer type refer to the same external object or function or are both the null pointer value and
— their corresponding non-type template-arguments of pointer-to-member type refer to the same class member or are both the null member pointer value and
— their corresponding non-type template-arguments of reference type refer to the same external object or function and
— their corresponding template template-arguments refer to the same template.

Put in context, this means that two instantiations of the same class template constitute two distinct data types even if they differ in the value of only a single non-type parameter.

jogojapan
  • 68,383
  • 11
  • 101
  • 131