在 C++ 中初始化静态 std::map<int, unique_ptr<int>>

Initializing a static std::map<int, unique_ptr<int>> in C++

这是一个与此 post 类似的问题。我认为最有前途的答案与模板化静态初始化有关。这是该答案的 class:

template <typename T, typename U>
class create_map
{
private:
    std::map<T, U> m_map;
public:
    create_map(const T& key, const U& val)
    {
        m_map[key] = val;
    }

    create_map<T, U>& operator()(const T& key, const U& val)
    {
        m_map[key] = val;
        return *this;
    }

    operator std::map<T, U>()
    {
        return m_map;
    }
};

用法:

std::map mymap = create_map<int, int >(1,2)(3,4)(5,6);

这对结构或 class 以及基本类型非常有用。我想做的是将它与 unique_prt<Structure\Class> 一起用作这样的值:

std::map mymap = create_map<DWORD, std::unique_ptr<Structure|Class>>(1, new Structure|Class())(2, new Structure|Class())

我正在尝试使用模板 class 以便我可以将值设置为任何类型。我从这个 post 得到了使用接口作为基础 class 然后派生的模板 class 来保存任何类型的值的想法。所以那些 classes 看起来像这样:

class MyFieldInterface
{
public:
    int m_Size;
    virtual ~MyFieldInterface() = default;
}

template <typename T>
class MyField : public MyFieldInterface {
    T m_Value; 
}

然后可以像我之前描述的那样设置地图:

std::map<DWORD, unique_ptr<MyFieldInterface>> mymap;

但是尝试用 create_map 初始化它失败了:

std::map mymap = create_map<DWORD, unique_ptr<MyFieldInterface>>(1, new MyField<DWORD>())(2, new MyField<char>())(3, new MyField<WORD>())

我得到的错误是这样的:

operator()
Error: no instance of constructor "create_map<T, U>::create_map [with T=DWORD, U=std::unique_ptr<MyFieldInterface, std::default_delete<MyFieldInterface>>]" matches the argument list
argument types are: (DWORD, MyField<DWORD>*)

所以我认为我需要一个构造函数和一个可以正确处理指针的 operator() 。我将两者都添加到 class:

create_map(const T& key, const U* val)
{
    m_map[key] = val;
}

create_map<T, U>& operator()(const T& key, const U* val)
{
    m_map[key] = val;
    return *this;
}

我遇到了同样的错误。所以我尝试没有 *:

create_map(const T& key, const U val)
{
    m_map[key] = val;
}

create_map<T, U>& operator()(const T& key, const U val)
{
    m_map[key] = val;
    return *this;
}

我遇到了同样的错误。在我写这篇文章时,我意识到问题可能与继承有关,不一定与 create_map 的运算符有关。 你能帮我找出 operator() 定义或 base/derived class 定义吗?

请限制您的回答不包括 Boost C++ 库,因为我在这里工作时不允许使用它们。

编辑:根据T.C的要求更新了 MyFieldInterface。

这是一种可能的实现方式:

template <typename T, typename U>
class create_map
{
private:
    std::map<T, U> m_map;
public:
    create_map(T key, U val)
    {
        m_map.emplace(std::move(key), std::move(val));
    }

    create_map&& operator()(T key, U val) &&
    {
        m_map.emplace(std::move(key), std::move(val));
        return std::move(*this);
    }

    operator std::map<T, U>() &&
    {
        return std::move(m_map);
    }
};

注意按值获取参数,然后使用 emplace 将其移动到映射中,以及从 m_map.

移动的转换运算符

我不知道 MSVC 2012 是否支持引用限定符。如果没有,则需要将其删除(即函数参数列表后的两个 &&)。这样做的目的是强制 create_map 只能用作临时值。也可以强制转换运算符只被调用一次,但我在上面的代码中没有这样做。

现在您的调用不能使用裸 news,因为 1) 它不是异常安全的,并且 2) 原始指针不能隐式转换为 unique_ptrs。不考虑数组的简单 make_unique 实现是

namespace util {
    template<class T, class... Args>
    std::unique_ptr<T> make_unique(Args&&... args) {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }
}

然后您可以将 new MyField<DWORD>() 更改为 util::make_unique<MyField<DWORD>>()*.

Demo.


* 使用合格的调用会禁用 ADL, if your call has arguments. A full implementation of make_unique according to the spec can be found in the example code in N3656make_unique 提案文件。

在 T.C 的指导下。由于 VC2012 中没有 make_unique,因此我从使用 unique_ptr<> 更改为 shared_ptr<>。

std::map mymap = create_map<DWORD, shared_ptr<MyFieldInterface>>(1, make_shared<MyField<DWORD>>())(2, make_shared<MyField<char>>())(3, make_shared<MyField<WORD>>())

这为我提供了我正在寻找的功能,而无需更改底层 类。虽然这符合我的需要,但我实际上会将 T.C. 的答案标记为正确,因为无论您使用哪个答案它都有效。