微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Std::map 持有任何类型的值

如何解决Std::map 持有任何类型的值

我想用“通用”值映射一个键,我的意思是它可以是一个整数、浮点数、字符、字符串等等。

我特别想这样做,因为我在模型中接收了转换后的 CAN 数据,并且可能的类型是(当前)int、float 和 string。

一个想法是创建一个可以以不同方式实现的抽象对象(每种设备类型一个),然后将其放入容器(映射或集合)中。

我认为使用“通用类型”作为值会更轻巧、更高效,这样当数据来自 CAN 总线时,容器将自动构建,而无需创建新的临时对象。

解决方法

如果您可以使用 C++17

std::variant 是您的选择。我询问了与您的问题相关的 question。波纹管我已经提供了如何实现它的示例:

#include <iostream>
#include <variant>
#include <assert.h>
#include <string_view>
#include <unordered_map>

enum class ValueType : uint8_t
{
    Undefined       = 0x00,Uint16,Uint32,AsciiString,};

typedef uint64_t FieldId;

struct FieldInfo
{
    std::string _name;
    ValueType _type;
    uint8_t size;   //  in bytes
};

typedef std::unordered_map<FieldId,FieldInfo> FieldContainer;

static FieldContainer requestFields =
{
    { 0,{ "user-id",ValueType::Uint32,sizeof (uint32_t) } },{ 1,{ "group-id",ValueType::Uint16,sizeof (uint16_t)} },{ 2,{ "user-name",ValueType::AsciiString,0} },};

std::variant<uint8_t,uint32_t,std::string_view> getValue(ValueType type,const uint8_t* data,size_t length)
{
    if (type == ValueType::Uint32)
    {
        assert(length == sizeof(uint32_t));
        return *reinterpret_cast<const uint32_t*>(data);
    }
    if (type == ValueType::Uint16)
    {
        assert(length == sizeof(uint16_t));
        return *reinterpret_cast<const uint16_t*>(data);
    }
    else if (type == ValueType::AsciiString)
    {
        return std::string_view(reinterpret_cast<const char*>(data),length);
    }

    return static_cast<uint8_t>(0);
}


int main(int argc,char *argv[])
{
    const uint8_t arr[] = {0x48,0x65,0x6c,0x6f,0x20,0x53,0x74,0x61,0x63,0x6b,0x4f,0x76,0x72,0x66,0x77,0x21};
    size_t length = sizeof(arr);

    const auto value0 = getValue(requestFields[0]._type,arr,requestFields[0].size);
    std::visit([](auto&& arg)
                    {
                        std::cout << "value-0: " << arg << std::endl;
                    },value0);


    const auto value1 = getValue(requestFields[2]._type,length);
    std::visit([](auto&& arg)
                    {
                        std::cout << "value-1: " << arg << std::endl;
                    },value1);

    return 0;
}

输出:

value-0: 1819043144
value-1: Hello StackOverflow!

UPD.0:我在这里没有使用 std::map,但我认为仅使用 std::variant 作为该容器的值没什么大不了的。 >

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。