你能切换一个 std::any.type() 吗?
Posted
技术标签:
【中文标题】你能切换一个 std::any.type() 吗?【英文标题】:can you switch over a std::any.type()? 【发布时间】:2020-12-14 15:42:58 【问题描述】:我想探索如何使用 std::any
而不是 void * 或类似的结构来传递消息。所以我创建了一个示例代码来测试它 - 见下文。
std::any 的使用看起来不错,但我想切换类型以检查 std::any 是哪种类型。这可能是不可能的,我知道我可以使用 if/elseif... 块代替,但是如果我可以创建一个 switch 语句,这样如果我在具有 10-20 种不同类型的实际代码中使用它,那就太好了它会更具可读性。
#include <string>
#include <iostream>
#include <sstream>
#include <any>
#include <typeindex>
struct ints int a1; int b2; ;
struct strings std::string a"string1"; std::string b"string2"; ;
void send_msg(std::any item)
switch (item.type().hash_code()) // <------- HERE
case typeid(ints).hash_code(): // <------- HERE
std::cout << "ints" << std::endl;
break;
case typeid(strings).hash_code():
std::cout << "strings" << std::endl;
break;
default:
std::cout << "unknown type\n";
int main()
strings s;
send_msg(s);
ints i;
send_msg(i);
实时示例:https://godbolt.org/z/xPrMYM
我无法打开 std::any::type 返回的 type_info,但我可以打开 type_info 的 hash_code()
,但这不是我希望的 constexpr!
所以我也尝试获取类型信息的地址以及我能找到的一些其他技巧。但到目前为止还没有运气......
有这样的方法吗?
【问题讨论】:
您可能正在寻找std::variant
和std::visit
Variant 也破坏了正确的对象并且具有类型安全性。
@code_fodder 没错,但any
只是一个不受约束的variant
,如果您切换类型表明您想要它是受约束的。
@code_fodder: "我读到它可以用来代替 void 之类的东西*" 它可以。如果您知道将其转换为正确的类型,您可以仅正确使用void*
。您不能使用void*
“切换类型”,因此您尝试做的事情也不适用于void*
。
@code_fodder:更重要的是,any
用于these circumstances
【参考方案1】:
如果可能的话,我也会在这里建议一个变体,但针对具体问题:
如果您可以使用 boost 并且 C++17 是您的参考标准:它们提供了扩展的 typeid 处理,也可以用于多个编译时检查,请参阅
https://www.boost.org/doc/libs/1_67_0/boost/type_index/ctti_type_index.hpp
它的底层 rawType 是一个 const char* constexpr,而 typeIndex 本身可以用作 std::type_info 的完美替代品。由于标准保证这些类型标识符的唯一地址,因此即使是简单的地址比较也应该可以在这里进行(不知道为什么这种简化目前在 boost 标头中被注释掉了)。
要与 any 一起使用,您可能必须包装它或使用简单的 own any 类型。
【讨论】:
【参考方案2】:你问的是std::visit
,但是std::any
template<typename... Ts, typename F>
bool visit(F&& f, std::any x)
auto result = ((x.type() == typeid(Ts) ?
(std::forward<F>(f)(*std::any_cast<Ts>(&x)), true) : false) || ...);
return result;
由于std::any
可能包含任何内容,visit
可能会在运行时失败,这就是为什么您当然需要某种方式来报告错误†。
用作
bool send_msg(std::any x)
auto f = [](auto&& x)
std::cout << x << '\n';
;
return visit<std::string, int>(f, x);
但是,使用std::variant
更简单
void send_msg(std::variant<std::string, int> x)
auto f = [](auto&& x)
std::cout << x << '\n';
;
visit(f, x);
†完整的visit
实现将是bit more complicated。
【讨论】:
以上是关于你能切换一个 std::any.type() 吗?的主要内容,如果未能解决你的问题,请参考以下文章