【问题标题】:How to store primitive types dynamically in one property?如何在一个属性中动态存储原始类型?
【发布时间】:2018-07-26 09:18:42
【问题描述】:

我是 C/C++ 的新手,通常我用 C# 编写代码,所以我有一个问题:

enum PrimitiveType {
    BOOL,
    STRING,
    INT8,
    INT16,
    INT32,
    UINT8,
    UINT16,
    UINT32,
};


struct MyValue
{           
public:  
    String Id         
    PrimitiveType ValueType;        
    [???] Value;         
};

我想在"Value" 属性中存储ints、strings 和bools。 在 C# 中,我会将Value 声明为一个对象,并将该对象转换为intbool,例如:

if(myValueObject.ValueType == BOOL)
    auto value = (bool)myValueObject.ValueType;

我可以在 C++ 中使用哪种类型?

【问题讨论】:

  • 没有“C/C++”语言。
  • 你可以为此使用联合类型

标签: c++ arduino esp32


【解决方案1】:

对此的规范答案是std::variant。不过,我会摆脱那个枚举,因为它引入了多个真相来源:

using PrimitiveValue = std::variant<bool, String, int8_t, int16_t, int32_t, uint8_t, uint16_t, uint32_t>;

struct MyValue {
    String id;
    PrimitiveValue val;
};

如果您绝对需要生成该枚举值,则需要一个映射:

PrimitiveType MyValue::getPrimitiveType() const {
    if (val.holds_alternative<bool>()) { return BOOL; }
    else if (val.holds_alternative<String>()) { return STRING; }
    else if (val.holds_alternative<int8_t>()) { return INT8; }
    // else ...
}

这样做可以确保永远不会出现类型描述符与实际存储的值不匹配的状态,因为variant 保证了这一点。

话虽如此,您对这种价值采取行动的“C# 方式”并不是这里的最佳选择。一个更好的是std::visit,它与该页面中的overloaded 帮助程序一起可以生成非常简洁的代码,根据存储的值执行不同的操作。

【讨论】:

  • 听起来很不错!问题是我没有变体类型。我认为这是因为我正在使用 PlatformIO 开发 ESP32。你知道我必须包含哪个库才能使用变体吗?
  • @Mr.Sheep 这是从 C++17 开始的标准库的一部分。您需要 #include &lt;variant&gt; 并确保您的编译器在启用 C++17 的情况下运行(例如 -std=c++17
【解决方案2】:

如前所述,std::variant 可能是最好的解决方案,但您需要 C++17。如果 C++17 是一个选项,你也可以使用std::any

如果您使用的是 C++17 之前的版本,我建议使用 union 声明。

【讨论】:

  • boost::variant(如果有)。
  • boost::any 也存在
猜你喜欢
  • 1970-01-01
  • 2011-09-19
  • 2014-01-16
  • 2012-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多