Skip to content

Latest commit

 

History

History
194 lines (142 loc) · 2.38 KB

variant.md

File metadata and controls

194 lines (142 loc) · 2.38 KB

std::variant<A,B,C,...>

A more perfect union.

C++14 C++17
struct Stuff
{
   union Data {
      int i;
      double d;
      string s;  // constructor/destructor???
   } data;
   enum Type { INT, DOUBLE, STRING } type;
};
struct Stuff
{




   std::variant<int, double, string> data;

};

Usage

C++14 C++17
void handleData(int i);
void handleData(double d);
void handleData(string const & s);

//...

switch (stuff.type)
{
case INT:
   handleData(stuff.data.i);
   break;
case DOUBLE:
   handleData(stuff.data.d);
   break;
case STRING:
   handleData(stuff.data.s);
   break;
}
void handleData(int i);
void handleData(double d);
void handleData(string const & s);

//...

std::visit([](auto const & val) { handleData(val); }, stuff.data);

// can also switch(stuff.data.index())
How the above lambda works
struct ThatLambda
{
   void operator()(int const & i) { handleData(i); }
   void operator()(double const & d) { handleData(d); }
   void operator()(string const & s) { handleData(s); }
};

ThatLambda thatLambda;
std::visit(thatLambda, stuff.data);

More Usage

C++17
if (holds_alternative<int>(data))
   int i = get<int>(data);

// throws if not double:
double d = get<double>(data);
C++17
std::variant<Foo, Bar> var;  // calls Foo()
// (or doesn't compile if no Foo())

Bar bar = makeBar();
var = bar; // calls ~Foo() and Bar(Bar const &)
// (what if Bar(Bar const & b) throws?)

var = Foo(); // calls ~Bar() and move-ctor Foo(Foo &&)
// (what if Foo(Foo && b) throws? - even though moves shouldn't throw)

var = someFoo;  // calls Foo::operator=(Foo const &)


std::variant<Foo, std::string> foostr;

foostr = "hello"; // char * isn't Foo or string
// yet foostr holds a std::string