【问题标题】:can you switch over a std::any.type()?你能切换一个 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 a{1}; int b{2}; };
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::variantstd::visit
  • Variant 也破坏了正确的对象并且具有类型安全性。
  • @code_fodder 没错,但any 只是一个不受约束的variant,如果您切换类型表明您想要它是受约束的。
  • @code_fodder: "我读到它可以用来代替 void 之类的东西*" 它可以。如果您知道将其转换为正确的类型,您可以正确使用void*。您不能使用void*“切换类型”,因此您尝试做的事情也不适用于void*
  • @code_fodder:更重要的是,any 用于these circumstances

标签: c++ c++17 any


【解决方案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

    【讨论】:

      猜你喜欢
      • 2013-05-15
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 2015-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多