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