Stream std :: any, не зная типа - PullRequest
0 голосов
/ 07 ноября 2018

Я хочу передать std::any, не зная значения.

Я знаю, что есть std::any.type(), но я не уверен, как его использовать в std::any_cast<type>(thatAny)

Это код, который я пробовал:

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

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Это не напрямую возможно.

Однако, если у вас есть T, не храните его напрямую, а храните {T, [](T const& t) { using std::to_string; return to_string(t); }}. То есть хранить с каждым T также лямбду, которая сериализует этот конкретный 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));}

0 голосов
/ 07 ноября 2018

Вы должны хранить, как передавать его куда-то.

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

Живой пример .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...