C++でバリアント型を使う。C++17以降。
#include <cstdio> #include <string> #include <variant> enum VARIANT_TYPES { V_INT = 0, V_STR = 1, V_DBL = 2 }; int main() { std::variant<int, std::string, double> val; val = 2; //val = 5.5; //val = "abc"; if (val.index() == V_INT) { int& x = std::get<V_INT>(val); printf("--- %d\n", x); }
else if(val.index()==V_STR){ std::string& s = std::get<V_STR>(val); printf("--- %s\n", s.c_str()); }
else if (val.index() == V_DBL) { double& d = std::get<V_DBL>(val); printf("--- %lf\n", d); } int k = getchar(); }
std::variant型を引数で取る関数を作ってもいいが、std::visit関数でoperator()を定義したクラスのインスタンスを渡して呼び出す方が美しいらしい。
#include <cstdio> #include <string> #include <variant>
struct Print { // int が代入されたときに呼び出される void operator()(const int& data) { printf("--- %d\n", data); } // std::string が代入されたときに呼び出される void operator()(const std::string& data) { printf("--- %s\n", data.c_str()); } // double が代入されたときに呼び出される void operator()(const double& data) { printf("--- %lf\n", data); } };
int main() { std::variant<int, std::string, double> val; val = 2; std::visit(Print(), val); val = 5.5; std::visit(Print(), val); val = "abc"; std::visit(Print(), val); int k = getchar(); }
std::visitは第一引数に関数、第二引数以降はstd::variant型でなければならない(らしい)。
std::visit( 関数() , variant1 , variant2 , variant3 , … )
なので、std::visitの引数で渡す場合、std::variantで渡さなければいけない。
#include <cstdio> #include <string> #include <variant> struct Print { // int が代入されたときに呼び出される void operator()(const int& data) { printf("--- %d\n", data); } // std::string が代入されたときに呼び出される void operator()(const std::string& data) { printf("--- %s\n", data.c_str()); } // double が代入されたときに呼び出される void operator()(const double& data) { printf("--- %lf\n", data); } };
struct Add { // int が代入されたときに呼び出される void operator()(int& data, const int val) { data += val; } // std::string が代入されたときに呼び出される void operator()(std::string& data, const int val) { data += std::to_string(val); } // double が代入されたときに呼び出される void operator()(double& data, const int val) { data += val; } };
int main() { std::variant<int, std::string, double> val; val = 2; std::visit( Add(), val,std::variant<int>(4) ); std::visit(Print(),val); val = 5.5; std::visit( Add(), val, std::variant<int>(4)); std::visit(Print(), val); val = "abc"; std::visit( Add(), val, std::variant<int>(4)); std::visit(Print(), val); int k = getchar(); }
引数を渡すならコンストラクタに渡した方がスマートだと思う。
#include <cstdio> #include <string> #include <variant>
struct Print { std::string _sign; public: Print(const std::string& sign):_sign(sign) {} // int が代入されたときに呼び出される void operator()(const int& data) { printf("%s %d\n",_sign.c_str(), data); } // std::string が代入されたときに呼び出される void operator()(const std::string& data) { printf("%s %s\n", _sign.c_str(), data.c_str()); } // double が代入されたときに呼び出される void operator()(const double& data) { printf("%s %lf\n", _sign.c_str(), data); } };
int main() { std::variant<int, std::string, double> val; val = 2; std::visit(Print(">>"),val); val = 5.5; std::visit(Print(">>"), val); val = "abc"; std::visit(Print(">>"), val); int k = getchar(); }