【问题标题】:Stream std::any without knowing the type在不知道类型的情况下流式传输 std::any
【发布时间】:2018-11-07 15:12:02
【问题描述】:

我想在不知道价值的情况下直播std::any

我知道有std::any.type(),但我不知道如何在std::any_cast<type>(thatAny)中使用它

这是我试过的代码:

std::cout << std::any_cast<a.type()>(a) << std::endl;

【问题讨论】:

  • type() 是一个运行时值,其中模板参数必须是编译时常量。
  • 经典问题,你需要创建一个函数并检查类型,对于每个相关类型,你调用std::any_cast。
  • 我会说std::any 对您要完成的任何任务都是错误的。
  • @MatthieuBrucher:如果你有这样的类型列表,为什么要使用std::any 而不是std::variant&lt;...&gt;
  • 确实如此。

标签: c++ c++17


【解决方案1】:

您需要存储如何在某处流式传输。

有几种不同的方法。如果您可以集中枚举或注册所有可以流式传输的类型,则可以创建从 typeid 到流式代码的映射,然后使用该映射流式传输您的特定 std::any

std::unordered_map< std::type_index, void(*)(std::any const&, std::ostream&)> streamers;

template<class T>
void add_streamer() {
  streamers[ typeid(T) ] = [](std::any const& a, std::ostream& os ) {
    os << std::any_cast<T>(a);
  };
}
template<class...Ts>
void add_streamers() {
  ( void(add_streamer<T>()), ... );
}

现在您可以流式传输了:

void stream( std::ostream& os, std::any const& a ) {
  streamers[ a.type() ]( a, os ); // maybe check errors!
}

另一种计划是增加您的 any 实例。

struct streamable_any : std::any {
  void(*streamer)(std::ostream&, streamable_any const&) = nullptr;
  friend std::ostream& operator<<( std::ostream& os, streamable_any const& a ) {
    a.streamer( os, a );
    return os;
  }
  template<class T,
    std::enable_if_t<!std::is_same<std::decay_t<T>, streamable_any>{}, bool> = true
  >
  streamable_any( T&& t ):
    std::any( std::forward<T>(t) ),
    streamer([](std::ostream& os, streamable_any const& self ) {
      os << std::any_cast<std::decay_t<T>>(self);
    } )
  {}
};

现在 streamable_any 现在只存储可流式传输的类型,并将如何将其流式传输到带有实例的函数指针中。

更安全的streamable_any 不会公开继承std::any,因为通过转换为基础修改std::any 会中断流式传输。只是因为any_cast之类的痛苦而已。

Live example.

【讨论】:

  • 我需要包含哪些内容?获取 type_index 和其他类型的错误。
  • @Mr.DeleteMyMessages Google“标准类型索引”。获取 cppreference 页面。点击它。在顶部观察它说明它是在哪个标题中定义的。
  • @Mr.DeleteMyMessages 另外,我修正了两个错别字,并链接了一个streamable_any running 的实时示例。
  • @steph no,但它可能会在完整的错误消息中说明问题所在。他们只是需要时间来解码。
  • @steph 是的,wstreamable_any 略有不同。
【解决方案2】:

直接不可能。

但是,如果您有 T,请不要直接存储它,而是存储 {T, [](T const&amp; t) { using std::to_string; return to_string(t); }}。 IE。与每个 T 一起存储,还有一个 lambda 序列化特定的 T

或者,您可以保持std::any 原样,但将其包装在自定义类型中,并将适当的[](std::any const&amp; a) { return to_string(std::any_cast&lt;T&gt;(a));}std::any 一起存储。例如。如果你插入一个int,你也会创建并存储一个[](std::any const&amp; a) { return to_string(std::any_cast&lt;int&gt;(a));}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多