当前位置: 首页 > 知识库问答 >
问题:

在C中初始化静态d::映射

蓟辰沛
2023-03-14

这是一个与这篇文章相似的问题。我认为最有希望的答案与模板化静态初始化有关。这是该答案中的类:

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一起使用

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

我试图使用一个模板类,这样我就可以拥有任何类型的值。我从这篇文章中得到一个想法,使用一个接口作为基类,然后使用一个模板派生类来保存任何类型的值。这些类看起来像这样:

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

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

然后可以像我前面描述的那样设置地图:

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>*)

所以我认为我需要一个可以正确处理指针的构造函数和一个运算符()。我将两者添加到类中:

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。


共有2个答案

孙弘博
2023-03-14

在T.C .的指导下,加上VC2012中没有make_unique,我不再使用unique_ptr

std::map mymap = create_map<DWORD, shared_ptr<MyFieldInterface>>(1, make_shared<MyField<DWORD>>())(2, make_shared<MyField<char>>())(3, make_shared<MyField<WORD>>())

这给了我一直在寻找的功能,而不必改变底层的类。虽然这符合我的需要,但我实际上要将T.C .的答案标记为正确,因为不管您使用哪一个,它都有效。

傅丁雷
2023-03-14

这是一种可能的实现:

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移动的转换运算符。

我不知道MSVC 2012是否支持裁判资格赛。如果没有,您需要删除它(这是两个<代码>

现在,您的调用不能使用裸news,因为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)...));
    }
}

然后,您可以更改新Myfield

演示。

*使用限定调用会禁用ADL,当您升级编译器时,如果您的调用有参数,这可能会产生令人惊讶的效果。根据规范,make_unique的完整实现可以在N3656中的示例代码中找到,make_unique提案文件。

 类似资料:
  • 尝试初始化变量时遇到问题: 我搜索了该怎么做,但没有找到。我读到要初始化的对象必须是静态的,但我找不到声明Map静态的方法。 谢谢你的帮助!

  • 问题内容: 我想知道静态变量(在类中)何时出现在图片中(初始化)?是在实例构造函数首次调用之后还是在类加载之后?什么时候加载类? 问题答案: 哦,那很复杂。这取决于是否设置了标志,而标志(在C#中)又取决于是否有静态构造函数。更糟的是;在.NET 4中, 我相信 行为发生了变化,使其比以前更加“懒惰”。 坦白说,我不会在此处编写任何特定行为的代码。简单:只要您使用常规代码访问静态字段,它们就会在尝

  • 问题内容: 这是一段Java代码: 它如何编译?初始化后已执行变量“ ture”的声明。据我所知,静态块和字段已经按照它们出现的顺序执行了。 现在,为什么实例块中的值9已被打印3次?顺便说一句,该类的实例已创建了3次。那不是功课,我正在学习Java进行认证。 问题答案: 关于第一个问题,静态块确实按照它们出现的顺序进行处理,但是在处理静态块之前,先处理声明。声明作为类 准备工作 的一部分(JLS§

  • 本文向大家介绍如何在C ++中初始化私有静态成员?,包括了如何在C ++中初始化私有静态成员?的使用技巧和注意事项,需要的朋友参考一下 在这里,我们将看到如何在C ++中初始化私有静态成员变量的初始化。我们可以将静态成员(函数或变量)放在C ++类中。对于静态变量,我们必须在定义类后对其进行初始化。 要初始化,我们必须使用类名称,然后使用范围解析运算符(::),然后使用变量名称。现在我们可以分配一

  • 问题内容: 我想知道为什么默认情况下C,C ++和Java中的确切静态变量初始化为零?为什么对局部变量不是这样? 问题答案: 为什么要对静态变量进行确定性初始化而对局部变量不进行初始化? 了解如何实现静态变量。 它们的内存在链接时分配,并且它们的初始值也在链接时提供。 没有运行时开销。 另一方面,用于局部变量的内存是在运行时分配的。堆栈必须增长。你不知道以前在那里。如果需要,可以清除该内存(将其清

  • 问题内容: 据我了解,“静态初始化块”用于设置静态字段的值(如果无法在一行中完成的话)。 但是我不明白为什么我们需要为此设置一个特殊的块。例如,我们将字段声明为静态(无值分配)。然后编写几行代码,生成并为上面声明的静态字段分配一个值。 为什么我们需要在这样一个特殊的块这样的行:? 问题答案: 在非静态块: 每次构造类的实例时被调用。在静态块只被调用一次,当类本身初始化,无论该类型的有多少对象创建。