Вы должны хранить, как передавать его куда-то.
Есть несколько разных подходов. Если вы можете централизованно перечислять или регистрировать все типы, которые вы можете передавать, вы можете создать карту от 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
и тому подобного.
Живой пример .