初始化静态std :: map< int,unique_ptr< int>>在C ++中 [英] Initializing a static std::map<int, unique_ptr<int>> in C++

查看:179
本文介绍了初始化静态std :: map< int,unique_ptr< int>>在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 news because 1) it isn't exception-safe and 2) raw pointers cannot be implicitly converted to unique_ptrs. 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&lt; int,unique_ptr&lt; int&gt;&gt;在C ++中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆