gpt4 book ai didi

c++ - 在 C++ 中初始化静态 std::map>

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:09:31 24 4
gpt4 key购买 nike

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

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com