模板typename问题

时间:2010-03-23 15:24:22

标签: c++ templates

我的模板有问题,并且想知道是否有可能实现我想要做的事情。这是我的问题。

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个参数,并将第2个类型的默认参数用作example_d。所以我可以实现1)但不是2)。因为我必须以这种方式编码

A<int, another_d> b(1, another_d()); 
输入有点太长了......

4 个答案:

答案 0 :(得分:3)

您无法存储类型,只能存储对象。

(如果要存储传递给d构造函数的参数A,请查看type erasure。)

答案 1 :(得分:2)

您无法“保存”类似的类型名称。你真正想做的是将类型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}}

答案 2 :(得分:1)

这看起来就像您正在尝试创建一个具有boost::any成员变量的模板类。你应该看看这是一种可行的方法。

基本上boost::any可以接受任何值类型。如果您稍后知道该类型,则可以安全地检索该类型。如何使用它的一个很好的例子是在地图中存储不同的数据类型(稍后当您通过名称检索any时,您知道该类型)。

如果这不是您正在寻找的内部,那么使用一个巧妙的技巧来实现它,它可能会帮助您实现您想要做的事情。

答案 3 :(得分:0)

如果要在A类的其他成员函数中使用类型D,可以将D作为A类的第二个模板参数。