3

I've the following:

template <template <typename, typename> class C, class T, class A >
class TTCTest
{
public:
        TTCTest(C<T, A> parameter) { /* ... some stuff... */ }
        C<T, A> _collection;
};

I want to ensure that the template is only instantiated where the T and A classes are of a specific type (path and allocator respectively).

For example:

...
list<path, allocator<path> > list1;
list<int, allocator<int> > list2;

TTCTest<list> testvar(list1); // ...should work
TTCTest<list> testvar(list2); // ...should not work
...

Is this possible and what is the syntax?

Regards, Col

ColB
  • 33
  • 1
  • 4
  • if C and T always have to be path and allocator, why should they be template parameters? – stijn Jan 10 '11 at 14:54
  • I guess I'm not good at this question asking! :-) I would like to specialize the template for those cases. – ColB Jan 10 '11 at 14:59
  • Then forward declare the general case, and provide a class body only for that particular partial specialization. – Ben Voigt Jan 10 '11 at 15:09
  • Hi Ben - I'm unsure of the syntax for doing so. Could you provide an example? – ColB Jan 10 '11 at 15:25
  • the answer depends on whether you need one class to work with your template (then partial specialization can be the solution) or you have a set of classes for which you want to have the same implementation (then constraining template instantiation can be a solution). – Gene Bushuyev Jan 10 '11 at 15:36
  • Hi Gene - it is the former case I am interested in. – ColB Jan 10 '11 at 15:41
  • Essentially - I am wanting to be able to pass in any collection but specialize for when the T (type) and A (allocator) of the given collection are specific types. – ColB Jan 10 '11 at 15:43

2 Answers2

3

You can do that with partial specialisation, where you fail to provide an implementation for the non-specialised case.
For example:

template <template <typename, typename> class C, class T, class A >
class TTCTest;

template <template <typename, typename> class C>
class TTCTest<C, path, allocator<path> >
{
  // ...
};
Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
1

You can create trait class to constraint instantiations. For example, limit your TTCTest construction only to path type:

template<class T, class A> class path {};
template<class T, class A> class not_path {};

template<class T> class allocation {};

template<class T>
struct Testable;

template<class T, class A>
struct Testable<path<T,A> > {};

template <template <typename, typename> class C, 
class T, class A >
class TTCTest
{
public:
        TTCTest(C<T, A> parameter, Testable<C<T,A> > = Testable<C<T,A> >());
        C<T, A> _collection;
};

void foo()
{
   path<int, allocation<int> > p;
   TTCTest<path, int, allocation<int> > t(p); // compiles

   not_path<int, allocation<int> > np;
   TTCTest<not_path, int, allocation<int> > t1(np); // fails
}

Edit: Since you indicated later that all you might need is partial specialization, in which case it would look like this:

template <class T, class A >
class TTCTest<path, T, A>
{
public:
        TTCTest(path<T, A> parameter);
        path<T, A> _collection;
};
Gene Bushuyev
  • 5,512
  • 20
  • 19