在不知道类型的情况下流std :: any

Mr.*_*ges 3 c++ c++17

我想在std::any不知道价值的情况下进行流式传输.

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

这是我试过的代码:

std::cout << std::any_cast<a.type()>(a) << std::endl;
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 6

你需要存储如何在某处传输它.

有几种不同的方法.如果您可以集中枚举或注册所有可以流式传输的类型,则可以创建从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>()), ... );
}
Run Code Online (Sandbox Code Playgroud)

现在你可以流:

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

另一种计划是扩充您的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);
    } )
  {}
};
Run Code Online (Sandbox Code Playgroud)

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

更安全的streamable_any不会公开继承std::any,因为修改std::any通过转换为基础会破坏流式传输.这只是一种痛苦any_cast等等.

实例.