Question

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?

Was it helpful?

Solution

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>
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top