【发布时间】:2021-09-20 12:14:19
【问题描述】:
我的目的是在每次获取值时从数据数组中获取任何值而不指定类型。我创建了描述字段信息(字段名称和类型)的特殊表格,还编写了一个函数来帮助我正确解释数据。
代码如下:
#include <iostream>
#include <variant>
#include <assert.h>
#include <string_view>
#include <unordered_map>
enum class ValueType : uint8_t
{
Undefined = 0x00,
Uint32,
AsciiString,
};
typedef uint64_t FieldId;
struct FieldInfo
{
std::string _name;
ValueType _type;
};
typedef std::unordered_map<FieldId, FieldInfo> FieldContainer;
static FieldContainer requestFields =
{
{ 0, { "user-id", ValueType::Uint32, } },
{ 1, { "group-id", ValueType::Uint32, } },
};
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);
}
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[] = {0x00, 0x11, 0x22, 0x33};
size_t length = sizeof(arr);
const auto value = getValue(ValueType::Uint32, arr, length);
std::visit([](auto&& arg)
{
if ( arg == 0x33221100 )
{
std::cout << "Value has been found" << std::endl;
}
}, value);
return 0;
}
我希望编译器能够正确推断返回值并让我进行数字比较。但是,我收到了以下编译器消息:
error: no match for ‘operator==’ (operand types are ‘const std::basic_string_view<char>’ and ‘int’)
57 | if ( arg == 0x33221100 )
| ~~~~^~~~~~~~~~~~~
error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
57 | if ( arg == 0x33221100 )
| ^~~~~~~~~~
| |
| int
我知道我可以通过调用std::get获得价值:
if ( std::get<uint32_t>(value) == 0x33221100 )
{
std::cout << "Value has been found" << std::endl;;
}
但这不是我想要达到的。
问题是 - 我可以使用所提供的方法来获取一个值,而无需在我需要的每个代码位置指定类型吗?
环境信息:
- 操作系统:Linux
- 编译器:g++ (GCC) 11.1.0
- 标准:C++17
【问题讨论】:
-
arg可以是uint8_t、uint32_t或std::string_view。 lambda 的主体必须对所有三个都有效。而当arg是std::string_view类型时,arg == 0x33221100没有意义。 -
编译器如何知道运行时包含什么变体?!
-
您似乎期望编译器查看
getValue内部,对其业务逻辑执行完整的语义分析,并推断当使用ValueType::Uint32调用时,它会产生一个持有uint32_t的变体。如果是这样,你的期望太高了。 -
如果您总是将硬编码常量作为
getValue的第一个参数传递,那么您最好只编写三个单独的函数,例如getInt8Value、getInt32Value和getStringValue,具有正确的返回类型,并且根本不用理会variant。事实上,您可以编写这些函数以及getValue来简单地调用它们。 -
嗯,这不是 C++ 的工作方式。这是一厢情愿的想法。