views:

328

answers:

3

I have a templated class A<T, int> and two typedefs A<string, 20> and A<string, 30>. How do I override the constructor for A<string, 20> ? The following does not work:

template <typename T, int M> class A;
typedef  A<std::string, 20> one_type;
typedef  A<std::string, 30> second_type;


template <typename T, int M>
class A {
public:
  A(int m) {test= (m>M);}

  bool test;

};


template<>
one_type::one_type() { cerr << "One type" << endl;}

I would like the class A<std::string,20> to do something that the other class doesn't. How can I do this without changing the constructor A:A(int) ?

+1  A: 

You can't with your current approach. one_type is an alias to a particular template specialization, so it gets whatever code the template has.

If you want to add code specific to one_type, you have to declare it as a subclass of A specialization, like this:

  class one_type:
    public A<std::string>, 20>
  {
    one_type(int m)
      : A<str::string, 20>(m)
    {
      cerr << "One type" << endl;
    }
  };
Franci Penov
Thought so. constructor's cannot be specialized as member functions, could you provide an argument for why not ?
Hassan Syed
Answered below :
Hassan Syed
+2  A: 

Assuming your really meant for A::test to be publicly accessible, you could do something like this:

#include <iostream>


template <int M>
struct ABase
{
  ABase(int n) : test_( n > M )
  {}

  bool const test_;
};


template <typename T, int M>
struct A : ABase<M>
{
  A(int n) : ABase<M>(n)
  {}
};


template <typename T>
A<T, 20>::A(int n)
  : ABase<20>(n)
  { std::cerr << "One type" << std::endl; }

Kick the tires:

int main(int argc, char* argv[])
{
  A<int, 20> a(19);
  std::cout << "a:" << a.test_ << std::endl;
  A<int, 30> b(31);
  std::cout << "b:" << b.test_ << std::endl;
  return 0;
}
seh
Good answer, going nuts with the type system :P
Hassan Syed
+2  A: 

The only thing you cannot do is use the typedef to define the constructor. Other than that, you ought to specialize the A<string,20> constructor like this:

template<> A<string,20>::A(int){}

If you want A<string,20> to have a different constructor than the generic A, you need to specialize the whole A<string,20> class:

template<> class A<string,20> {
public:
   A( const string& takethistwentytimes ) { cerr << "One Type" << std::endl; }
};
xtofl