C++ 是否有一种更干净的方法可以在c+中复制具有多类型值的无序#u映射+;(11)

C++ 是否有一种更干净的方法可以在c+中复制具有多类型值的无序#u映射+;(11),c++,types,unordered-map,C++,Types,Unordered Map,基本思想是获得一个无序的_映射,该映射存储不同类型的值。我试图做的是为OpenGL统一缓冲区对象创建一个易于访问的对象。最终产品看起来像: UBO ubo = { "Uniforms", "translation", "scale", "rotation", "enabled" }; ubo["scale"] = 0.5f; ubo["translation"] = { 0.1f, 0.1f, 0.0f }; ubo["rotation"] = { 90.0f, 0.0f, 0

基本思想是获得一个无序的_映射,该映射存储不同类型的值。我试图做的是为OpenGL统一缓冲区对象创建一个易于访问的对象。最终产品看起来像:

UBO ubo = { "Uniforms", "translation", "scale", "rotation", "enabled" };
ubo["scale"]       = 0.5f;
ubo["translation"] = { 0.1f, 0.1f, 0.0f };
ubo["rotation"]    = { 90.0f, 0.0f, 0.0f, 1.0f };
ubo["enabled"]     = GL_TRUE; 
在我的UBO类中,我有重载运算符[]:

struct UBOData;

class UBO
{
    std::unordered_map<std::string,UBOData>
    ...
    public: 
    UBOData &operator[](std::string key)
    {
        UBOData data = new UBOData();
        dataMap.emplace(key, data);
        return data;
    }

    const UBOData& operator[](std::string key)
    {
        return const_cast<UBOData&>(*this)[key];
    }
};
我已经截断了这个示例中的类型,没有std::array类型。还请注意,我正在使用一个空*来存储值,并告诉我需要重新思考我的设计。我当然会,这就是我来这里的原因:)

我试图用类型检查来包装void*,但是有没有更好的方法来获得没有void*的多类型映射


注意:我在Windows上使用VS2013,在Mac和Linux上使用clang。

boost::variant
boost::any

如果您不能或不想使用boost,请阅读他们所做的

我会自己选择变体。

当然。这就是它建造的目的。以下是使用您的代码的示例:

#include <unordered_map>
#include <vector>
#include <boost/variant.hpp>

class UBO
{
    using UBOData = boost::variant<float, std::vector<float>>;
    std::unordered_map<std::string, UBOData> dataMap;
    public: 
    UBO() : dataMap(){}
    UBOData &operator[](const std::string& key)
    {
        return dataMap[key];
    }
};

int main()
{
   UBO ubo;
   ubo["scale"]       = 0.5f;
   ubo["translation"] = std::vector<float>{ 0.1f, 0.1f, 0.0f };
   ubo["rotation"]    = std::vector<float>{ 90.0f, 0.0f, 0.0f, 1.0f };
}
#包括
#包括
#包括
UBO类
{
使用UBOData=boost::variant;
std::无序地图数据地图;
公众:
UBO():数据映射(){}
UBOData和运算符[](常量标准::字符串和键)
{
返回数据映射[键];
}
};
int main()
{
UBO UBO;
ubo[“刻度”]=0.5f;
ubo[“translation”]=std::vector{0.1f,0.1f,0.0f};
ubo[“旋转”]=标准::向量{90.0f,0.0f,0.0f,1.0f};
}

如果您想要
{0.1f,0.1f,0.0f}
语法而不键入
std::vector
等,您可能需要某种类型的代理来处理初始值设定项列表。

您是否考虑过使用类型的多态层次结构,存储指向基类的(智能)指针?然后,您可以通过让映射在每个元素上调用
clone()
方法来“复制”(copy)映射。或者,你可以考虑Boost变体或者Boost。这让我找到了这个链接:与您的问题无关:您的
操作符[]
的常量版本根本不是常量。这没有道理。@c.r.看起来像是试图使用非
const
版本,但失败得很惨。@c.r.你说得对。这是一个复制粘贴错误。谢谢。是的,从上面TonyD的评论中我看到了这两种结构。我还发现了另一个与这个主题相关的链接,其中有一个有趣的花絮,谢谢。我将进一步研究boost变体。boost::variant可以接受两个以上的模板参数吗?@SethHays:可以,最多20个。
int &UBOData::operator=(int lhs)
{
    if (type == Undefined) { type = rInt; } else { assert(type == rInt); }
    value = new int(lhs);
    int &rValue = *((int*)value);
    return rValue;
}

float &UBOData::operator=(float lhs)
{
    if (type == Undefined) { type = rFloat; }
    else { assert(type == rFloat); }

    value = new float(lhs);
    float &rValue = *((float*)value);
    return rValue;
}

double &UBOData::operator=(double lhs)
{
    if (type == Undefined) { type = rDouble; }
    else { assert(type == rInt); }

    value = new double(lhs);
    double &rValue = *((double*)value);
    return rValue;
}
#include <unordered_map>
#include <vector>
#include <boost/variant.hpp>

class UBO
{
    using UBOData = boost::variant<float, std::vector<float>>;
    std::unordered_map<std::string, UBOData> dataMap;
    public: 
    UBO() : dataMap(){}
    UBOData &operator[](const std::string& key)
    {
        return dataMap[key];
    }
};

int main()
{
   UBO ubo;
   ubo["scale"]       = 0.5f;
   ubo["translation"] = std::vector<float>{ 0.1f, 0.1f, 0.0f };
   ubo["rotation"]    = std::vector<float>{ 90.0f, 0.0f, 0.0f, 1.0f };
}