初始化静态std :: map< int,unique_ptr< int>>在C ++中 [英] Initializing a static std::map<int, unique_ptr<int>> in C++
问题描述
这是对此帖子的类似问题.我认为最有希望的答案与模板化静态初始化有关.这是该答案的课程:
This is a similiar question to this post. The answer that I think has the most promise has to do with templated static initialization. Here is the class from that answer:
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>
用作这样的值:
This works great for a structure or a class as well as the base types. What I would like to do is to use this with a unique_prt<Structure\Class>
as the value like this:
std::map mymap = create_map<DWORD, std::unique_ptr<Structure|Class>>(1, new Structure|Class())(2, new Structure|Class())
我正在尝试使用模板类,以便可以将值设置为任何类型.我从帖子中获得了使用接口作为基础的想法类,然后是模板派生的类,以保存任何类型的值.因此,这些类如下所示:
I am trying to use a template class so that I can have the value be any type. I got the idea from this post to use an interface as a base class and then a template derived class to hold any type of value. So those classes look like this:
class MyFieldInterface
{
public:
int m_Size;
virtual ~MyFieldInterface() = default;
}
template <typename T>
class MyField : public MyFieldInterface {
T m_Value;
}
然后可以像我之前描述的那样设置地图:
Then the map can be setup like I described earlier:
std::map<DWORD, unique_ptr<MyFieldInterface>> mymap;
但是尝试使用create_map初始化它失败:
But trying to initialize it with create_map fails:
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().我将两者都添加到了该类中:
So I thought that I need a constructor and an operator() that can handle the pointer properly. I added both to the 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;
}
我遇到了同样的错误.所以我尝试了没有*
:
I got the same error. So I tried without the *
:
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()定义或基类/派生类定义吗?
I got the same error. As I'm writing this, I realized that the problem may be related to the inheritance and not necessarily create_map's operator. Can you help me figure out the operator() definition or the base/derived class definition that I need to get this to work?
请限制您的答案以不包括Boost C ++库,因为我不允许在工作中使用它们.
编辑:按照T.C的要求更新了MyFieldInterface.
Edit: updated MyFieldInterface as requested by T.C.
推荐答案
这是一种可能的实现方式:
This is one possible implementation:
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
移出的转换运算符将其移入映射.
Note the taking argument by value and then moving it into the map with emplace
, and the conversion operator that moves from m_map
.
我不知道MSVC 2012是否支持引用限定符.如果不是,则需要将其删除(即功能参数列表后面的两个&&
).这样做的目的是强制create_map
仅应用作临时文件.还可以强制转换操作符仅被调用一次,但是在上面的代码中我没有这样做.
I don't know if MSVC 2012 supports ref-qualifiers. If it doesn't, you'll need to remove it (that's the two &&
s after the function parameter list). The point of that is to enforce that create_map
should only be used as a temporary. It is possible to also enforce that the conversion operator is only called once, but I didn't do that in the code above.
现在您的呼叫无法使用裸new
,因为1)它不是异常安全的,并且2)无法将原始指针隐式转换为unique_ptr
.一个不考虑数组的简单make_unique
实现是
Now your calls cannot use naked new
s because 1) it isn't exception-safe and 2) raw pointers cannot be implicitly converted to unique_ptr
s. A simple make_unique
implementation that doesn't take arrays into account is
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>>()
* .
演示.
* 使用限定的呼叫将禁用ADL,该 N3656 make_unique的完整实现. a>,make_unique
投标文件.
* Using a qualified call disables ADL, which can have surprising effects when you upgrade your compiler if your call has arguments. A full implementation of make_unique
according to the spec can be found in the example code in N3656, the make_unique
proposal paper.
这篇关于初始化静态std :: map< int,unique_ptr< int>>在C ++中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!