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

时间:2018-11-07 15:12:03

标签: c++ c++17

我想流std::any而实际上不知道其值。

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

这是我尝试过的代码:

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

2 个答案:

答案 0 :(得分: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>()), ... );
}

现在您可以流式传输:

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

答案 1 :(得分:2)

不可能直接

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

或者,您可以按原样保留std::any,但可以将其包装为自定义类型,并在[](std::any const& a) { return to_string(std::any_cast<T>(a));}旁边存储适当的std::any。例如。如果您插入int,则还将创建并存储一个[](std::any const& a) { return to_string(std::any_cast<int>(a));}