2012-12-09 77 views
4

对于像std::map< std::string, std::unique_ptr<Foo>>这样的容器,它好像emplace()还没有在stdC++中实现,如gcc 4.7.2。用什么来代替std :: map :: emplace?

不幸的是,我不能直接按值存储Foo,因为它是一个抽象的超类。

作为一个简单但效率低下的占位者,我刚刚使用std::map< std::string, Foo* >std::vector< std::unique_ptr<Foo>>一起进行垃圾回收。

一旦emplace()可用,您是否拥有更高效且更易于更换的临时解决方案?

回答

11

你需要什么emplace()?只要将它移动在:

#include <iostream> 
#include <map> 
#include <memory> 
#include <string> 

struct Foo 
{ 
    virtual ~Foo() = default; 

    virtual std::string name() const = 0; 
}; 

struct Bar : Foo 
{ 
    std::string name() const { return "Bar"; } 
}; 

int main() 
{ 
    std::map<std::string, std::unique_ptr<Foo>> m; 

    std::unique_ptr<Foo> p(new Bar()); 
    m.insert(std::make_pair("a", std::move(p))); 

    std::cout << m["a"]->name() << std::endl; 
} 

事实上,you should not use emplace with unique_ptr's

正如我在我的评论中指出的那样,我现在考虑在用户代码中使用new的错误。它应该被替换为make_unique,所以你知道你的资源不可能泄漏:

// will be in std:: someday 
template <typename T, typename... Args> 
std::unique_ptr<T> make_unique(Args&&... args) 
{ 
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 
} 

int main() 
{ 
    std::map<std::string, std::unique_ptr<Foo>> m; 

    m.insert(std::make_pair("a", make_unique<Bar>())); 

    std::cout << m["a"]->name() << std::endl; 
} 
+0

+1对于使用可用代码很好的答案。避免在用户代码中使用'new'是一个勇敢的原因。然而,假设我没有构建Bar的新实例,而是因为我不知道我有什么样的'Foo',所以我需要在映射中插入'foo-> clone()'。你将如何使'Foo * Bar :: clone()'避免调用'new'?或者这是好的,因为它不会被视为客户端代码? – kfmfe04

+1

巧合的是我今天刚刚处理过。取而代之,让你的克隆函数返回'std :: unique_ptr '。 – GManNickG

+0

我知道这有点旧,但如果foo-> clone()的用户想要一个shared_ptr呢? –

2

正如你可以使用一种变通方法,boost容器支持最即使在一个C++ 03的编译器C++ 11的功能,并具有相同的布局std容器中,然后当你再在你拥有std你可以切换一个名字空间!

相关问题