2

I have a class looking like this:

#include <vector>
#include "record.h"
#include "sortcalls.h"

template<
    typename T,
    template<typename , typename Allocator = std::allocator<T> > class Cont = std::vector>
class Sort: public SortCall {

This code is working and I'm calling it like this from other classes:

Comparator c; // comparison functor
Sort< Record, std::vector > s(c);

Now I want to be able to switch the containers to another container, say a list. So I thought a typedef would be neat. It should be something like

typedef std::vector<Record> container;  // Default record container

template<
    typename T,
    template< typename, typename container > // ???
class Sort: public SortCall {
mre
  • 1,813
  • 4
  • 28
  • 37
  • 1
    I'm not sure I understand; you're not using `Sort` anywhere. Also, `_Alloc` is reserved for the compiler; you should change that to just `Allocator` or something. – GManNickG Feb 10 '10 at 21:54
  • 1
    I'm not sure I understand why the template parameters have to be this complicated. Why not `template class Sort...` with `Sort s`? – UncleBens Feb 10 '10 at 22:05
  • Actually, you should just delete `_Alloc` and the default value, neither is required and supplying them doesn't help anything. (I'm not even sure the default value there is legal C++.) –  Feb 10 '10 at 22:07
  • @RogerPate `_Alloc` does compile and run (even with my own containers). But I'm glad to learn that it's no good style :) – mre Feb 10 '10 at 22:21
  • @UncleBens YES this is actually working! Am I right that I won't loose any flexibility to sort other things than records with that? – mre Feb 10 '10 at 22:24

3 Answers3

5

Don't use template template parameters (Cont in your code), they are brittle and inflexible. Use a rebind mechanism if you need to (std::allocator is an example), but you don't in this case:

template<class T, class Cont=std::vector<T> >
struct Sort {
  typedef Cont container_type; // if you need to access it from outside the class
  // similar to std::vector::value_type (which you might want to add here too)
};

typedef Sort<int, std::list<int> > IntListSort;

Compare to std::queue and std::stack, which also follow this pattern.

  • Using this design over template template parameters is one of those things a lot of us learn the hard way, with lots of squinting at the standard and scratching of the head. +1. – Derrick Turk Feb 10 '10 at 22:19
  • This might be the best solution for future development. You get my vote. Although UncleBens provided the first working solution. Thx all! – mre Feb 10 '10 at 22:34
0

You should be able to use 'container' directly after typename as you have it in your example. It's type specification will be expanded when the compiler runs.

Try compiling it...

Jordan Parmer
  • 36,042
  • 30
  • 97
  • 119
0

I think it might be easier if you use type traits. Every container in STL and boost has number off typedef, among them value_type (consult reference http://www.cplusplus.com/reference/stl/vector/). So your code may look like:

template<class C>
class sort {
  typedef typename C::value_type value_type; // equivalent to T in your case.
  // similarly you can get allocator, iterator, etc.
Anycorn
  • 50,217
  • 42
  • 167
  • 261