在统一的内联初始化中使用不可复制的值初始化static std :: map

U. *_*lle 8 c++ noncopyable static-initialization c++17

我想初始化一个std::map值不可复制的静态.我将调用我的类ValueClass.ValueClass有一个std::unique_ptr私有成员,我甚至通过扩展non_copyable看起来如下所示确保ValueClass不可复制:

class non_copyable {
public:
    non_copyable() = default;
protected:
    virtual ~non_copyable() = default;
private:
    non_copyable(const non_copyable&) = delete;
    non_copyable& operator=(const non_copyable&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试使用我的类作为值来定义std :: map:

static std::map<int, ValueClass> value_classes = {
    {0, ValueClass()},
    {1, ValueClass() }
};
Run Code Online (Sandbox Code Playgroud)

initializer_list尝试复制此类时出现编译错误.

make_map本周末我试图在整个周末编写自己的函数来启用初始化而不复制但是我失败了.我试过这个,其他,但他们没有与Visual Studio编译15.9.4.

如何使用Visual Studio编译器初始化静态std :: map,其中copy不是强制的,并且初始化在一个函数中是统一的?

编辑: 这是现实生活场景的简化版本,我正在尝试使其工作(原谅我缺乏命名约定和案例的不一致):

#include <iostream>
#include <map>

class non_copyable {
public:
    non_copyable() = default;
protected:
    virtual ~non_copyable() = default;
private:
    non_copyable(const non_copyable&) = delete;
    non_copyable& operator=(const non_copyable&) = delete;
};

class InnerValueClass : public non_copyable
{
public:
    InnerValueClass(const int inner_number) : inner_number_(inner_number) {  }
private:
    int inner_number_;
};

class ValueClass : public non_copyable
{
public:
    ValueClass(const int number1) : number1_(number1) {  }
    ValueClass(const bool condition) : condition_(condition), inner_value_(
        std::make_unique<InnerValueClass>(5)) {  }
private:
    int number1_{};
    bool condition_{};
    std::unique_ptr<InnerValueClass> inner_value_{};
};

/* Inline initialization of std::map copies, this is for initialization of non-copy types*/
template <typename TKey, typename TNonCopyableValue>
class make_map_by_moving
{
    typedef std::map<TKey, TNonCopyableValue> map_type;
    map_type map_;
public:
    make_map_by_moving(const TKey& key, TNonCopyableValue&& val)
    {
        map_.emplace(key, std::move(val));
    }
    make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
    {
        map_.emplace(key, std::move(val));
        return *this;
    }
    operator const map_type&()
    {
        return map_;
    }
};

static std::map<int, ValueClass> map =
        make_map_by_moving<int, ValueClass>
                (1, ValueClass(5))
                (2, ValueClass(true));
/* It goes on like this for hundreds of lines, so I really appreciate any
solution that leave me with a clean initialization rather than calling
functions on std::map */

int main() { }
Run Code Online (Sandbox Code Playgroud)

重复编辑:该问题中提供的解决方案不适用于我的类结构.我也在寻找一种解决方法来修复make_map_by_moving函数,换句话说就是内联初始化,答案提供了一个功能调用的必要解决方案.

Bar*_*rry 6

您不能直接执行此操作,因为initializer_listconst支持所有元素 - 并且必须将它们从初始化列表复制到容器中.显然,这需要复制.遗憾的是,没有办法从初始化列表中放置.

在C++ 17中,由于保证了复制省略,你可以这样做:

std::map<int, non_copyable> get() {
    std::map<int, non_copyable> m;
    m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
    m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
    return m;
}

std::map<int, non_copyable> value_classes = get();
Run Code Online (Sandbox Code Playgroud)

此代码不执行任何副本non_copyable.我们将构造内部置于其中map,然后beacuse get()是一个prvalue,没有复制/移动get()进入value_classes.所述mget() 对象value_classes.

一个稍微运动的方法就是滥用try_emplace()这个:

std::map<int, non_copyable> get() {
    std::map<int, non_copyable> m;
    m.try_emplace(0);
    m.try_emplace(1);
    return m;
}
Run Code Online (Sandbox Code Playgroud)

try_emplace()int单独获取键类型(因此你可以只传递一个),然后单独使用emplacing的值的参数,这使得完成此任务的方式更加简洁.


Mat*_*her 4

insert_or_assign我认为您需要在函数中创建对象,然后返回它:

std::map<int, ValueClass> populate()
{
    std::map<int, ValueClass> value_classes;
    value_classes.insert_or_assign(std::make_pair(0, ValueClass());
    return value_classes;
}
Run Code Online (Sandbox Code Playgroud)

你的初始化变成:

std::map<int, ValueClass> value_classes = populate();
Run Code Online (Sandbox Code Playgroud)

但是,这个类有一个虚拟析构函数,这意味着您实际上想要的实际上可能是std::map<int, std::unique_ptr<ValueClass>>实际对象的映射而不是实际对象的映射(不确定这些对象将用于什么?)。

问题编辑后编辑:

在这种情况下,Barry s suggestion is the one to follow, usingemplace`:

std::map<int, ValueClass> populate()
{
    std::map<int, ValueClass> value_classes;
    value_classes.emplace(1, 5);
    return value_classes;
}
Run Code Online (Sandbox Code Playgroud)

还包括functional.