указатели как параметры шаблона? - PullRequest
9 голосов
/ 16 июля 2009

У меня есть контейнерный класс, мы назовем его

template <class T> CVector { ... } 

Я хочу сделать что-то другое с этим классом, когда T является типом указателя, например что-то вроде:

template <class T*> CVector< SomeWrapperClass<T> >;

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

Почему это так? Я хочу изменить, в очень большом приложении, как работают некоторые из наших контейнеров, когда тип, для которого они специализируются, является указателем, а не указателем - и в идеале, я хотел бы сделать это без изменения ~ 1000 мест в коде, где есть такие вещи, как CVector<Object*> против CVector<int> или что-то в этом роде, и кажется, что играть в игры с частичной специализацией - путь.

Я нахожусь здесь?

Ответы [ 6 ]

7 голосов
/ 16 июля 2009

Если я вас правильно понимаю, это может сделать то, что вы хотите:

template<typename T>
class CVector { ... };

template<typename T>
class CVector<T*> : public CVector< SomeWrapperClass<T> > {
public:
  // for all constructors:
  CVector(...) : CVector< SomeWrapperClass<T> >(...) {
  }
};

Добавляет дополнительный уровень наследования к уловке CVector<T*> в CVector< SomeWrapperClass<T> >. Это также может быть полезно, если вам нужно добавить дополнительные методы для обеспечения полной совместимости между ожидаемым интерфейсом для T* и предоставленным интерфейсом для SomeWrapperClass<T>.

5 голосов
/ 16 июля 2009

Это прекрасно работает в C ++ ...

#include <iostream>

template <class T>
class CVector
{
public:
    void test() { std::cout << "Not wrapped!\n"; }
};

template <class T>
class CVector<T*>
{
public:
    void test() { std::cout << "Wrapped!\n"; }
};

int main()
{
    CVector<int> i;
    CVector<double> d;
    CVector<int*> pi;
    CVector<double*> pd;
    i.test();
    d.test();
    pi.test();
    pd.test();
}
4 голосов
/ 16 июля 2009

Не думаю, что вы можете специализировать класс, используя синтаксис, который вы описали ... Я не знаю, как это могло бы сработать. Что вы можете сделать, так это специализировать класс для указателей и заново реализовать его внутренности, используя класс-оболочку для необработанных указателей. Я не уверен, поможет ли это, но эта статья описывает специализированные шаблоны для указателей.

1 голос
/ 16 июля 2009

Библиотека черт типа Boost может помочь вам в этом. Проверьте черту типа is_pointer .

#include <boost/type_traits.hpp>
#include <iostream>
#include <vector>

using namespace std;

template <class T>
class CVector {
  public:
    void addValue(const T& t) {
      values_.push_back(t);
    }

    void print() {
      typedef boost::integral_constant<bool,
        ::boost::is_pointer<T>::value> truth_type;

      for (unsigned int i = 0; i < values_.size(); i++) 
        doPrint(values_[i], truth_type());
    }


  private:
    void doPrint(const T& t, const boost::false_type&) {
      cout << "Not pointer. Value:" << t << endl;
    }

    void doPrint(const T& t, const boost::true_type&) {
      cout << "Pointer. Value: " << *t << endl;
    }

    std::vector<T> values_;
 };


int main() {
  CVector<int> integers;
  integers.addValue(3);
  integers.addValue(5);
  integers.print();

  CVector<int*> pointers;
  int three = 3;
  int five = 5;
  pointers.addValue(&three);
  pointers.addValue(&five);
  pointers.print(); 
}
0 голосов
/ 22 января 2013

Я согласен с ответом rlbond. Я немного изменил его, чтобы удовлетворить ваши потребности. CVector может быть производным классом самого CVector. Затем вы можете использовать разные члены и функции для него.

#include <iostream>
#include <string>
template <class T>
class CVector
{
public:
    void test() { std::cout << "Not wrapped!\n"; }
    void testParent() { std::cout << "Parent Called\n";}
};

template <class T>
class CVector<T*>:
    public CVector<T>
{
public:
    void test(std::string msg) { std::cout << msg; testParent(); }
};

int main()
{
    CVector<int> i;
    CVector<double> d;
    CVector<int*> pi;
    CVector<double*> pd;
    i.test();
    d.test();
    pi.test("Hello\n");
    pd.test("World\n");
    system("pause");
}
0 голосов
/ 16 июля 2009

Я не думаю, что шаблоны настолько гибки.

Подход, основанный на грубой силе, заключается в том, чтобы специализироваться для всех ваших типов указателей ... что снимает проблему использования шаблонов.

Не могли бы вы иметь другой класс CVector, который используется только для векторов указателей?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...