簡體   English   中英

將try_emplace與shared_ptr一起使用

[英]Using try_emplace with a shared_ptr

所以我有一個std::unordered_map<std::string, std::shared_ptr<T>> ,我想用try_emplace添加/引用元素。 以前,它只是一個std::unordered_map<std::string, T>T有一個僅使用std::string的構造函數,所以我在使用myMap.try_emplace(myString, myString).first->second引用T並在必要時創建它。

但是,如果我只是將其更改為myMap.try_emplace(myString, std::make_shared<T>(myString)).first->second ,則當然每次都會構造T

解決此問題的最慣用的方法是什么? 為了明確起見,我想使用共享指針在堆上構造對象,並且僅當映射中沒有匹配元素時,才將共享指針插入到無序映射中。

您可以使用operator[]代替:

auto &ptr = map[ key ];
if( !ptr ) ptr = std::make_shared<T>( myString );

注意:此解決方案假設您不想在映射中保留默認構造的std::shared_ptr 如果是這種情況,那么您需要在try_emplace使用更多詳細代碼:

auto p = map.try_emplace( key, nullptr );
if( p.second ) p.first->second = std::make_shared<T>( myString );
else {
    if( !p.first->second ) { // handle nullptr }
}
auto &ptr = p.first->second;

另一種選擇是將共享指針包裝為您自己的類型。 然后,您可以提供一個構造函數,該構造函數接受一個T並創建一個shared_ptr<T> 這樣,您就可以使用try_emplace並將其傳遞給T而無需在對象已經存在的情況下實際創建任何內容。 但是,如果要使用該對象就像是shared_ptr<T> ,則會涉及很多樣板。

編寫工廠函數包裝器:

template<class F>
struct auto_factory_t {
  F f;
  operator decltype(std::declval<F&&>()()) && {
    return std::move(f)();
  }
};
template<class F>
auto_factory_t<std::decay_t<F>> wrap_factory(F&&f){
  return {std::forward<F>(f)};
}

然后

myMap.try_emplace(myString, wrap_factory([&]{return std::make_shared<T>(myString);})).first->second;

並做了。

wrap_factory(f)返回包含f的對象。 可以將其隱式轉換為f()返回的類型,完成后調用f()

您可以做什么:

// C++17, else you have to move declaration outside of the `if`
// and retrieve it/inserted from pair result.
if (auto [it, inserted] = myMap.try_emplace(myString, nullptr); inserted) {
    it->second = std::make_shared<T>(myString);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM