типовое имя вопроса - PullRequest
       6

типовое имя вопроса

3 голосов
/ 23 марта 2010

У меня проблема с шаблоном, и мне интересно, есть ли способ достичь того, что я хотел сделать. Вот мой вопрос.

template <typename T>
class A
{
public:

    typedef T*              pointer;
    typedef const pointer   const_pointer;

    A()
    {}

    template <typename D>
    A(const D& d)
    {
        // how can I store the D type 
        // so I can refer it later on
        // outside of this function
    }
};

Хорошо, вот более полный код того, что я хотел сделать (возможно, он не компилируется)

    class C
{
public:
    virtual ~C(){}

    virtual void* get_d() = 0;
private:

};

template <typename T, typename D>
class Cimpl : public C
{
public:
    Cimpl()
    :t()
    ,d()
    {}

    Cimpl(const T& t, const D& d)
    :t(t)
    ,(d)
    {}

    void* get_d()
    {
        return &reinterpret_cast<D&>(d);
    }

private:
    T t;
    D d;
};

class B
{
public:
    B()
    :p(0)
    {}

    template <typename T, typename D>
    B(const T& t, const D& d)
    :p(0)
    {    
        try
        {
            p = new Cimpl<T, D>(t, d);
        }
        catch(...)
        {
            d(p);
        }
    }

    void* get_d()
    {
        return (p != 0) ? p->get_d() : 0;
    }

    ~B()
    {
      delete p;
    }

private:
    C* p;
};

template <typename T>
class A
{
    struct example_d
    {
    };

public:

    typedef T*              pointer;
    typedef const pointer   const_pointer;

    A()
    {}

    template <typename D>
    A(const T& t)
    :b(t, example_d())
    {
    }

    template <typename D>
    A(const T& t, const D& d)
    :b(t, d)
    {
        // how can I store the D type 
        // so I can refer it later on
        // outside of this function
    }

    // not type safe...as user can cast to any type
    // if I can store the type user pass in previous
    // then I can use it back
    template <typename T>
    T* get_d()
    {
        reinterpret_cast<T*>(b.get_d());
    }

private:
    B b;
};

Так что я могу использовать класс как

1)A<int> a(1);// with example_d as D
2)A<int> b(1, another_d()) // with another_d

Я могу изменить шаблон так, чтобы он принимал 2 параметра, и использовать параметр по умолчанию для второго типа, который будет example_d. Так что я могу достичь 1), но не 2). Как мне придется кодировать этот путь

A<int, another_d> b(1, another_d()); 

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

Ответы [ 4 ]

3 голосов
/ 23 марта 2010

Вы не можете сохранить тип, вы можете хранить только объекты.

(Если вы хотите сохранить параметр d, переданный конструктору A, посмотрите на type erasure .)

2 голосов
/ 23 марта 2010

Вы не можете "сохранить" такое имя типа. Что вы действительно хотите сделать, так это сделать тип D одним из параметров шаблона класса, например

template <typename T, typename D>
class A
{
public:

    typedef T*              pointer;
    typedef const pointer   const_pointer;

    A()
    {}

    A(const D& d)
    {
    }
};

Теперь, если ваша проблема в том, что вы хотите, чтобы A<T> с типом D был полиморфным с A<T> с типом E вместо A<T,D> и A<T,E> двух разных типов, решение базового класса:

template <typename T>
class ABase
{
public:

    typedef T*              pointer;
    typedef const pointer   const_pointer;

    ABase()
    {}

protected:

    /* You might want to omit this constructor completely, 
     * depending on your use case */

    template<typename D>
    ABase(const D& d)
    {
    }
};

template <typename T, typename D>
class A : public ABase<T>
{
public:

    A()
    {}

    A(const D& d)
      : ABase(d)
    {
    }
};
1 голос
/ 23 марта 2010

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

В основном boost::any может принимать любой тип значения. Затем вы можете безопасно получить этот тип, если знаете его позже. Хороший пример того, как вы могли бы использовать это, - хранить различные типы данных на карте (где вы узнаете тип позже, когда вы получите any по его имени).

Если это не совсем то, что вы ищете, то используйте внутреннюю хитрость для его реализации, и это, вероятно, поможет вам достичь того, что вы пытаетесь сделать.

0 голосов
/ 23 марта 2010

Если вы хотите использовать тип D в других функциях-членах класса A, вы можете сделать D вторым параметром шаблона класса A.

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