7

I have a std::vector of std::any, all of which can be printed via << (e.g., only ints and floats). I'd love to have something like

#include <experimental/any>
#include <iostream>
#include <vector>

int main() {
  std::vector<std::experimental::any> v;

  v.push_back(1);
  v.push_back(3.14);

  for (const auto& a: v) {
    std::cout << a << std::endl;
  }

  return 0;
}

but that doesn't work since std::any doesn't know <<:

error: no match for ‘operator<<’

The only workaround I've come up with so far is to explicitly cast the vector items into whatever data type might be in it, e.g.,

#include <experimental/any>
#include <iostream>
#include <vector>

int main() {
  std::vector<std::experimental::any> v;

  v.push_back(1);
  v.push_back(3.14);

  for (const auto& a: v) {
    try {
        std::cout << std::experimental::any_cast<int>(a) << std::endl;
    } catch (const std::experimental::fundamentals_v1::bad_any_cast&)
    {}

    try {
        std::cout << std::experimental::any_cast<double>(a) << std::endl;
    } catch (const std::experimental::fundamentals_v1::bad_any_cast&)
    {}
  }

  return 0;
}

This is (perhaps unnecessarily) verbose and also rather inflexible since once has to know all data types that might occur in the vector.

Is there a variant of vector<any> printing without those disadvantages?

Nico Schlömer
  • 53,797
  • 27
  • 201
  • 249

1 Answers1

10

You are using the wrong type. Since "only ints and floats" are stored here, then what you clearly want is a std::variant<int, float>, not an any. You can then print such a vector easily enough:

for (const auto& a: v) {
  std::visit([](const auto &val) {std::cout << val << std::endl;}, a);
}

any is primarily for communication between two locations through an intermediary, where the start point and end point both know the exact type to be used, but the intermediary does not. Think of a signaling system; the sender and receiver of the signal know what type to use, but the signaling system doesn't care.

Applying an operation over a small, fixed range of types is more variant territory. Applying an operation over an unbounded range of types is some form of genuine polymorphism: either compile-time (templates) or runtime (virtual functions).

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982