Otay, I was brushing up my coding skills by creating a basic, coding 101 list class. At this point it works fine with a generic value, either primitive type or class. If it's a class, all the relational operators need to be overloaded to match the class key.

I suddenly got it into my head that it'd be an excellent idea if there the list node could work with both a generic value and a key. Less overloading, easier sorting, puppies and ice cream...

So I'm thinking of going from:
template <class LISTDATA>
to
template <class LISTKEY, class LISTDATA>

My problem lies with the "could" part of that sentence. What if the main program is declaring a list using only a key variable. I'd like the key/data split to be optional. If the program only calls for an integer, there's no sense in having anything other than a Key value, right?

I tried a small practice run and something like
list <int> l;
doesn't work. It expects two... parameters? in the brackets. So I haven't actually started this project yet.

I've searched the Interwebz without success. I think part of my problem is I don't know what to call what I'm trying to do. Or if it's even a good idea in the first place.

Recommended Answers

All 3 Replies

That's why default-types exist.

Consider the Map interface, it is declared as follows--

template < class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key,T> > > class map;

Notice how class Compare = less<Key> and class Allocator = allocator<pair<const Key, T>>

That means, if someone calls the Map with only 2 template parameters, the other 2 are assigned the default types however the user has a choice of also assigning those types to his/her own specific classes that satisfy the template parameters.

So the user has several options on how to use the Map template.

If you want to allow several options (via template parameters) on how a user constructs your list objects, you would want something like--

template <class LISTDATA, class LISTKEY = int>

-- unfortunately you must define from R-to-L in template parameters and I don't think 'gaps' are allowed. But this way you can explicitly tell your class what type of key you want when you want to use that option. With the above change, this should be allowed--

list <unsigned int> l; // data-type 'unsigned int', key 'int'
list <unsigned int, short> m; // data-type 'unsigned int, key 'short'

-- although this might seem counter-intuitive upon declaration and usage, keep in mind the map template itself does not make a default key either.

You can also use template specialization with a template... you can avoid the ordering problem of the default template argument. What I mean is this:

//create a placeholder struct for key types
template <class T>
struct key { };

//create a placeholder struct for data types
template <class T>
struct data { };

template <class T>
class list;
  //intentionally left with no generic implementation, to catch illegal uses of list.

//now specialize for key types:
template <class T>
class list< key<T> > {
  //put the implementation for the key-version of list
};

//now specialize for data types:
template <class T>
class list< data<T> > {
  //put the implementation for the data-version of list
};

//instantiate as follows:
list< data<int> > l;
list< key<short> > m;

You can also have a general implementation for key and data with a default for each, without the ordering issue:

template <class Key, class Data>
class list_details {
  //generic key and data implementation.
};

//now specialize for key types:
template <class T>
class list< key<T> > {
  template <class Data = unsigned int> //some default type like "unsigned int"
  typedef list_details< T, Data> type;
};

//now specialize for data types:
template <class T>
class list< data<T> > {
  template <class Key = short>
  typedef list_details<Key, T> type;
};

//instantiate as follows:
list< key<int> >::type a;      //list with "int" keys and default data-type "unsigned int"
list< key<int> >::type<int> b; //list with "int" keys and "int" data.
list< data<int> >::type c;     //list with "int" data and default "short" keys.

I think this works, it's a little convoluted, but that's template meta-programming, it's convoluted by definition.

commented: Purely awesome. +0

Thank you guys! I will play around with mapping and specialization until I get the hang of it... especially specialization. ;)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.