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

标签 c++ templates inheritance static-initialization

这是一个与此 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);

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

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

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

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

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

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

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() 定义或基类/派生类定义吗?

请限制您的回答不包括 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 将其移动到 map 中,以及从 m_map 移动的转换运算符.

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

现在你的电话不能使用裸new s 因为 1) 它不是异常安全的并且 2) 原始指针不能隐式转换为 unique_ptr秒。一个简单的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>() s 至 util::make_unique<MyField<DWORD>>() *.

Demo .


* 使用限定调用会禁用 ADL,这 can have surprising effects when you upgrade your compiler如果您的电话有参数。全面实现 make_unique根据规范可以在 N3656 中的示例代码中找到, make_unique提案文件。

关于c++ - 在 C++ 中初始化静态 std::map<int, unique_ptr<int>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28901848/

相关文章:

c++ - 从我的 .exe 中隐藏纯文本字符串

c++ - 为什么 std::string 关系运算符比较结果对于模板和函数是不同的?

c++ - 查找并替换字符数组中的单词

c++ - 使用 header 时,是否需要插入我的 cpp 文件中使用的每个函数?

c++ - 使用可变参数将函数转换回原始签名

c++ - const std::shared_ptr<const T> 作为函数的参数最终会改变智能指针中类的值

c++ - 在对象继承中构造对象后设置较晚的值

java - Exception Java 的异常构造函数

c++ - 要从 Clion 的 C++ 项目中的 VCS 中删除哪些文件?

c++ - 使用 Winsock DLL 在简单的 TCP 回显服务器中分离消息