2010-03-23 90 views
3

我有一个模板的问题,不知道有没有可能的方式来实现我想做的事。这是我的问题。模板类型名称问题

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()); 

有点太长型...

+2

不能存储类型本身,但也有变通方法。你想用D做什么? – 2010-03-23 15:29:24

+2

参数'T'有什么意义?这与问题有什么关系? – Seb 2010-03-23 15:30:11

+0

我没有澄清我实际上想做什么。我想要一个类只需要一个模板参数。然后另一个模板类型提供参数构造函数。我可以在课程的其他部分使用D型,而不仅仅是类型D的通过 – stephenteh 2010-03-23 15:40:15

回答

3

不能存储类型,你只能存储对象。

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

+1

这是一个很好的类型擦除链接。 – iain 2010-03-23 22:57:17

2

你不能‘拯救’这样的类型名。你真正想做的是让类型D成为该类的模板参数之一,例如现在

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

    typedef T*    pointer; 
    typedef const pointer const_pointer; 

    A() 
    {} 

    A(const D& d) 
    { 
    } 
}; 

,如果你的问题是,你想与D型构造A<T>具有多态性与E型构造,而不必A<T,D>A<T,E>是两种不同类型的A<T>,那么该解决方案是一个基类:

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) 
    { 
    } 
}; 
0

如果你想使用类型d A类的其他成员函数,可以使d类A的第二个模板参数

+1

其实我知道这一点,但我只需要一个模板参数。所以想知道有没有办法。谢谢 – stephenteh 2010-03-23 15:31:25

+0

你有什么理由不能拥有两个模板参数吗?如果是这样的话,你可以从另一个类Abase派生出A,它将D作为它的模板参数。 – Dima 2010-03-23 15:34:35

+1

@stephenteh:你如何告诉我们你想要存储'D'的? – sbi 2010-03-23 15:35:49

1

这看起来像你正试图创建一个具有boost::any成员变量的模板类。你应该看看这是一个可能的方式。

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

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