Reputation: 3902
Given the following class
template <class T>
class A {
static const B<T> member;
};
how can I instantiate member
for each class A<T>
separately?
Upvotes: 3
Views: 181
Reputation: 1627
Simple. As you would with any other static non-integral type.
template <class T>
class A {
static const B<T> member;
};
template <class T>
const B<T> A<T>::member/*(optional-args)*/;
In order to allocate member differently for different types of T
, you must use template specialisation.
To start the template specialisation you must use this syntax:
template<>
// ... explicit definition
The syntax for the explicit definition is basically the same syntax as:
template <class T>
const B<T> A<T>::member/*(optional-args)*/;
Except, instead of template <class T>
, you use template<>
, and where T
is, you put the actual type.
For example:
template<>
const B<type> A<type>::member(args);
NOTE: If you wish to call the default constructor with template specialisation in this scenario, please see the EDIT below.
You can substitute type
for any type you wish. With this you can provide different arguments for each possible type. Although if you specialise too much, you should consider if your design is really suited to use templates.
Here it is in action (online), feel free to clone and play around with it.
I thought I'd mention that the declaration must be where the template class is located. In other words, if A
is declared in the header, you must also declare the allocation for member
in the header file. You can alternatively use an inline file (.inl) and #include
the .inl file in the header file that the template class is declared.
It seems that in C++98, the following syntax to call the default constructor does not compile under GCC or clang, if you refer to the member variable:
template <>
const B<type> A<type>::member/*()*/;
Where type is any type.
However the following does:
template <class T>
const B<T> A<T>::member/*()*/;
I'm not sure if this is a bug, or just incorrect syntax. I recommend instead to do the following:
template <>
const B<type> A<type>::member = B<type>();
Or if you are using C++11, you can use curly brackets to call the default-constructor, like so:
template <>
const B<type> A<type>::member{};
If you use regular brackets, the compiler will thing it is a static function within the A<type>
class, and if you use no brackets, you will get an undefined reference to 'A<type>::member'
linker error. Which you can see here.
Here is the discussion that Aaron and I discovered this error.
Upvotes: 6