Reputation: 1141
Class definition is as follows:
template<typename T, list_node T::* node> class linked_list
{
// ...
};
and can be instantiated like:
linked_list<foo, &foo::node> list;
But I would like a way to allow the user to instantiate as follows:
linked_list<foo> list2;
and have a specialization of the linked_list class which works differently. Can anyone tell me if this is possible and, if so, how to do it?
[EDIT]
template<typename T, list_node T::* node = nullptr> struct linked_list
{
};
followed by:
template <typename T> struct linked_list<T, nullptr>
{
};
gives me an error in VS2013:
error C2754: 'linked_list' : a partial specialization cannot have a dependent non-type template parameter
Should this be legal under the standard or have I misunderstood the answer below?
Upvotes: 1
Views: 353
Reputation: 136256
To allow for one template argument you need to default the second one to something, e.g. nullptr
:
template<typename T, list_node T::* node = nullptr> class linked_list;
Now you can specialize linked_list<T, nullptr>
template that is used when the second template argument is nullptr
:
template<typename T> class linked_list<T, nullptr>;
The above specialization does not work. An alternative way to specialize (complete working example):
struct list_node {};
struct X { list_node node; };
template<typename T, list_node T::*P, bool Special>
struct linked_list_ {};
template<typename T, list_node T::*P>
struct linked_list_<T, P, true> {};
template<typename T, list_node T::*P = nullptr>
struct linked_list
: linked_list_<T, P, static_cast<list_node T::*>(nullptr) == P>
{};
int main() {
linked_list<X, &X::node> a; // uses linked_list_<T, P, false>
linked_list<X> b; // uses linked_list_<T, P, true>
}
Upvotes: 1