C ++ шаблонная специализация конструктора - PullRequest
7 голосов
/ 14 декабря 2009

У меня есть шаблонный класс A и две определения типа A и A . Как переопределить конструктор для A ? Следующее не работает:

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;}

Я бы хотел, чтобы класс A делал то, чего не делает другой класс. Как я могу сделать это без изменения конструктора A: A (int)?

Ответы [ 6 ]

8 голосов
/ 14 декабря 2009

Единственное, что вы не можете сделать, это использовать typedef для определения конструктора. Кроме этого, вы должны специализировать конструктор A<string,20> следующим образом:

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

Если вы хотите, чтобы A<string,20> имел конструктор , отличающийся от общего A, вам нужно специализировать весь класс A<string,20>:

template<> class A<string,20> {
public:
   A( const string& takethistwentytimes ) { cerr << "One Type" << std::endl; }
};
6 голосов
/ 14 декабря 2009

Предполагая, что ваше действительно предназначено для A::test, чтобы быть общедоступным, вы можете сделать что-то вроде этого:

#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; }

пинаем шины:

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;
}
1 голос
/ 16 января 2018

Это может быть немного поздно, но если у вас есть доступ к c++11, вы можете использовать SFINAE , чтобы выполнить то, что вам нужно:

  template <class = typename std::enable_if< 
    std::is_same<A<T,M>, A<std::string, 20>>::value>::type // Can be called only on A<std::string, 20>
  > 
  A() {
    // Default constructor
  }

Рабочий пример

1 голос
/ 13 декабря 2010

Как насчет:

template<typename T, int M, bool dummy = (M > 20) >
class A {
public:
  A(int m){
      // this is true
  }

};

template<typename T, int M>
class A<T,M,false> {
public:
    A(int m) {
    //something else
    }
};
1 голос
/ 14 декабря 2009

Вы не можете с вашим текущим подходом. one_type - это псевдоним определенной специализации шаблона, поэтому он получает любой код, который есть в шаблоне.

Если вы хотите добавить код, специфичный для one_type, вы должны объявить его как подкласс специализации A, например:

  class one_type:
    public A<std::string, 20>
  {
    one_type(int m)
      : A<str::string, 20>(m)
    {
      cerr << "One type" << endl;
    }
  };
0 голосов
/ 08 ноября 2016

Лучшее решение, которое я смог найти в этой ситуации, это использовать «вспомогательную функцию конструктора»:

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 {
private:
  void cons_helper(int m) {test= (m>M);}
public:
  A(int m) { cons_helper(m); }

  bool test;
};

template <>
void one_type::cons_helper(int) { cerr << "One type" << endl;}
...