2012-09-02 49 views
2

我想写的很简单任何对象,它可以容纳任何类型的对象。我希望它在容器内部使用,来实现异构容器。在“异构对象”类中复制构造函数

#include <iostream> 
#include <vector> 
#include <string> 

struct Any 
{ 
    template < typename T > 
    Any(const T & t) 
     :p(new storageImpl<T>(t)) { } 

    ~Any() 
    { 
     delete p; 
    } 

    struct storage 
    { 
     virtual ~storage() {} 
    }; 

    template <typename T> 
    struct storageImpl : storage 
    { 
     storageImpl(const T & t) : data(t) {} 
     T data; 
    }; 

    template <typename T> 
    T & get() 
    { 
     storageImpl<T> * i = static_cast<storageImpl<T>*>(p); 
     return i->data; 
    } 

    storage * p; 
}; 

使用

int main() 
{ 
    //block1 
    Any copy(Any(std::string("foo")));  
    std::cout << copy.get<std::string>(); 

    //block2 
    std::vector<Any> cont; 
    cont.push_back(Any(5)); 
    cont.push_back(Any(37.9f)); 
    std::cout << cont[0].get<int>();  
    std::cout << cont[1].get<float>(); 
} 

我有一份建设问题。

当我将Any推入向量(// block2)时,未命名的Any被破坏,所以指针被删除,并且推送的对象不再有效。

所以我有2个问题:

1,如何编写类中的任何拷贝构造函数?

2,为什么不是无名Any在BLOCK1破坏,因此它的指针不会被删除?\

编辑 我曾尝试

template <typename T> 
Any(const Any & rhs) 
    :p(new storageImpl<T>(rhs.get())) 
{ 
} 

但它不会被触发。

+1

如果您不知道,已经有[Boost.Any](http://www.boost.org/doc/libs/1_51_0/doc/html/any.html)。 – kennytm

+0

@KennyTM我知道,但我不想使用提升。 – relaxxx

回答

2

Any不是模板类。试图将复制构造器模板化为template <typename T> Any(const Any & rhs)是没有意义的。

你可以做的是使用virtual constructor成语,让storageImpl自己复制。这也是Boost.Any中使用的方法。

struct Any { 
    template < typename T > 
    Any(const T& t) : p(new storageImpl<T>(t)) {} 

    Any(const Any& other) : p(other.p->clone()) {} 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

    ~Any() { delete p; } 

    struct storage { 
     virtual ~storage() {} 
     virtual storage* clone() = 0; 
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    }; 

    template <typename T> 
    struct storageImpl : storage { 
     storageImpl(const T & t) : data(t) {} 

     virtual storage* clone() { return new storageImpl(data); } 
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

     T data; 
    }; 

    template <typename T> 
    T& get() { 
     storageImpl<T>* i = static_cast<storageImpl<T>*>(p); 
     return i->data; 
    } 

    storage * p; 
}; 

请注意,此实现有很多问题,例如, get()方法将不检查Any是否真的拥有T.使用经过良好测试的库例如Boost.Any


为什么不无名任何BLOCK1破坏,因此它的指针不会被删除?

Copy elision

+0

非常感谢Kenny,类型检查不是一个真正的问题,我打算只用一次,因为一个小问题,所以我不想使用boost。 – relaxxx

1
  1. 做一个深拷贝,即动态地分配一个新对象storageImpl<T>,初始化为来自物体的一个的被复制的内容。

  2. 您可以有copy elision发生,这意味着没有临时对象被删除。

或者,使用boost::any避免所有问题。

+0

谢谢,但是如何编写这样的构造函数?请参阅编辑我的问题以了解我所尝试的内容。并感谢'复制elision' – relaxxx

+0

@relaxxx你确定代码编译器?您在'const'引用上调用非const方法'get()'。其实,看起来你需要知道'rhs'的'T'才能复制。 – juanchopanza