mapbox / variant

C++11/C++14 Variant
BSD 3-Clause "New" or "Revised" License
371 stars 101 forks source link

Add variant_static_cast, variant_dynamic_cast #144

Closed narizhny closed 7 years ago

narizhny commented 7 years ago
class Base {public: virtual ~Base(){}};
class A: public Base {};
class B: public Base {};

typedef mapbox::util::variant<A, B> T;
T t = A();
auto &base = mapbox::util::variant_static_cast<Base>(t);
auto &a = mapbox::util::variant_dynamic_cast<A>(t);
auto &b = mapbox::util::variant_dynamic_cast<B>(t); //throws std:bad_cast
auto *aPtr = mapbox::util::variant_dynamic_cast<A*>(t);
auto *bPtr = mapbox::util::variant_dynamic_cast<B*>(t); //bPtr == nullptr
artemp commented 7 years ago

@narizhny - thanks for the PR! Could you add unit tests for the casts? And could you share a use-case for this usage if you have one?

narizhny commented 7 years ago

@artemp Yes, I'll do it.

daniel-j-h commented 7 years ago

What's the use-case for this? Is this to replicate the interface in http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast

if so we're missing a few casts here. If not, why not simply get the underlying value and let the user cast herself? Not sure if a larger API surface is a good thing here.

narizhny commented 7 years ago

static cast is usefull, where all types derived from one

class VehicleBase 
{
public:
    ~VehicleBase(){}
    void run() {}
};

class Car: public VehicleBase {};
class Bus: public VehicleBase {};
class Tracktor: public VehicleBase {};

using Vehicle = mapbox::util::variant<Car, Bus, Tracktor>;

std::vector<Vehicle> garage;

//I need to run all vehicles! What should i do? Write visitor? if-else-if-else..., or just
for(auto &v: garage)
    mapbox::util::static_variant_cast<VehicleBase>(v).run();
narizhny commented 7 years ago

const and reinterpret casts? Hmm... I didn't think about it.