Есть ли более чистый способ репликации unordered_map с многотипными значениями в c ++ (11)

Основная идея заключается в том, чтобы получить 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.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];
}
};

И я использую UBOData для хранения разных типов данных. Вот где моя уверенность падает в свете того, что является «правильным» в мире с ++.

.
.
.
struct UBOData
{
enum ReturnType {Undefined, rInt, rFloat, rDouble};

void       *value;
ReturnType type;
int &operator=(int lhs);
float &operator=(float lhs);
double &operator=(double lhs);
};

Я сократил типы для этого примера, нет типов std :: array. Также обратите внимание, что я использую void * для хранения значения и скажите мне, что мне нужно переосмыслить свой дизайн. Конечно я делаю, поэтому я здесь 🙂

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;
}

Я пытался обернуть void * проверкой типов, но есть ли лучший способ получить многопечатную карту без void *?

Примечание: я использую VS2013 для Windows и Clang для Mac и Linux.

0

Решение

определенно повышение :: вариант. Вот для чего он построен. Вот маленький пример используя ваш код:

#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 };
}

Если вы хотите { 0.1f, 0.1f, 0.0f } синтаксис без ввода std::vector<float>и т. д., возможно, вам потребуется прокси-сервер определенного типа, который обрабатывает списки инициализаторов.

0

Другие решения

boost::variant или же boost::any,

Если вы не можете или не будете использовать повышение, прочитайте, что они сделали.

Я бы пошел с variant себя.

2

По вопросам рекламы [email protected]