2012-12-09 76 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你可以切換一個名字空間!

相關問題