初始化静态 std::map unique_ptr 作为值
Initialize static std::map with unique_ptr as value
如何初始化静态映射,其中值std::unique_ptr
?
static void f()
{
static std::map<int, std::unique_ptr<MyClass>> = {
{ 0, std::make_unique<MyClass>() }
};
}
当然这是行不通的(删除了std::unique_ptr
的复制者)。
可能吗?
问题是从std::initializer-list
构造会复制其内容。(std::initializer_list
中的对象本质上是const
的)。要解决您的问题:您可以从单独的函数初始化地图...
std::map<int, std::unique_ptr<MyClass>> init(){
std::map<int, std::unique_ptr<MyClass>> mp;
mp[0] = std::make_unique<MyClass>();
mp[1] = std::make_unique<MyClass>();
//...etc
return mp;
}
然后称之为
static void f()
{
static std::map<int, std::unique_ptr<MyClass>> mp = init();
}
在科里鲁现场观看
编写定制的新月代码似乎很无聊,并且妨碍了清晰度。
下面是相当有效的通用容器初始化代码。 它像初始值设定项列表一样将您的数据存储在临时std::array
中,但它会移出而不是使其const
。
make_map
采用偶数个元素,第一个是键,第二个值。
template<class E, std::size_t N>
struct make_container_t{
std::array<E,N> elements;
template<class Container>
operator Container()&&{
return {
std::make_move_iterator(begin(elements)),
std::make_move_iterator(end(elements))
};
}
};
template<class E0, class...Es>
make_container_t<E0, 1+sizeof...(Es)>
make_container( E0 e0, Es... es ){
return {{{std::move(e0), std::move(es)...}}};
}
namespace details{
template<std::size_t...Is, class K0, class V0, class...Ts>
make_container_t<std::pair<K0,V0>,sizeof...(Is)>
make_map( std::index_sequence<Is...>, std::tuple<K0&,V0&,Ts&...> ts ){
return {{{
std::make_pair(
std::move(std::get<Is*2>(ts)),
std::move(std::get<Is*2+1>(ts))
)...
}}};
}
}
template<class...Es>
auto make_map( Es... es ){
static_assert( !(sizeof...(es)&1), "key missing a value? Try even arguments.");
return details::make_map(
std::make_index_sequence<sizeof...(Es)/2>{},
std::tie( es... )
);
}
这应该将其减少到:
static std::map<int, std::unique_ptr<MyClass>> bob =
make_map(0, std::make_unique<MyClass>());
。除非有错别字。
活生生的例子。
另一种方法是使用 lambda。 这与使用单独的函数相同,但使地图的初始化更接近操作。在这种情况下,我使用了auto&和decltype的组合来避免命名地图的类型,但这只是为了好玩。
请注意,传递给 lambda 的参数是对在调用时尚未构造的对象的引用,因此我们不得以任何方式引用它。它仅用于类型推断。
#include <memory>
#include <map>
#include <utility>
struct MyClass {};
static auto& f()
{
static std::map<int, std::unique_ptr<MyClass>> mp = [](auto& model)
{
auto mp = std::decay_t<decltype(model)> {};
mp.emplace(0, std::make_unique<MyClass>());
mp.emplace(1, std::make_unique<MyClass>());
return mp;
}(mp);
return mp;
}
int main()
{
auto& m = f();
}
这是另一种方式。在本例中,我们已将临时变量传递到 lambda 中,并依赖于 copy elision/RVO。
#include <memory>
#include <map>
#include <utility>
struct MyClass {};
static auto& f()
{
static auto mp = [](auto mp)
{
mp.emplace(0, std::make_unique<MyClass>());
mp.emplace(1, std::make_unique<MyClass>());
return mp;
}(std::map<int, std::unique_ptr<MyClass>>{});
return mp;
}
int main()
{
auto& m = f();
}
还有另一种方式,在可变的 lambda 中使用 lambda 捕获。
#include <memory>
#include <map>
#include <utility>
struct MyClass {};
static auto& f()
{
static auto mp = [mp = std::map<int, std::unique_ptr<MyClass>>{}]() mutable
{
mp.emplace(0, std::make_unique<MyClass>());
mp.emplace(1, std::make_unique<MyClass>());
return std::move(mp);
}();
return mp;
}
int main()
{
auto& m = f();
}
相关文章:
- 为什么 std::unique 不调用 std::sort?
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 为共享 ptr 向量实现复制 c'tor?
- 字符和整数中 **(ptr+1) 的值差异
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 生成"unique"矩阵
- 如何将派生类从基 ptr 分配给 nlohmann::json
- 引用 std::shared:ptr 以避免引用计数
- 我对 std::unique(算法)C++有问题
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- 尝试打印出 *ptr++ 的值,以了解它是如何工作的
- 如何控制共享 ptr 引用计数?
- std::shared_ptr::unique(),复制和线程安全
- 如何在C++03中用自定义谓词调用std::unique
- C++中的指针否定 (!ptr == NULL)
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误