背景
std::visit
+ overloaded(パターンマッチング)便利ですよね.
C++11, C++14 でもやりたいですね!
C++14 以下で std::variant
の実装は variant-lite があります.
overloaded テンプレートについては, using Ts::operator()...;
は C++17 の構文なので, C++11, C++14 でやるとコンパイルエラーになります.
で C++11, C++14 でやる方法ありました!
例
template <class... Fs> struct overload_set;
template <class F1, class... Fs>
struct overload_set<F1, Fs...> : F1, overload_set<Fs...>::type
{
typedef overload_set type;
overload_set(F1 head, Fs... tail)
: F1(head), overload_set<Fs...>::type(tail...)
{}
using F1::operator();
using overload_set<Fs...>::type::operator();
};
template <class F>
struct overload_set<F> : F
{
typedef F type;
using F::operator();
};
template <class... Fs>
//auto overload(Fs... x) for C++14
typename overload_set<Fs...>::type overload(Fs... x)
{
return overload_set<Fs...>(x...);
}
nonstd::variant<int, float, std::string> Var;
Var v = 2;
std::string ty = nonstd::visit(overload (
[](auto) { return "[[TODO]]"; },
[](int) { return "int"; }
), v);
std::cout << ty;
Voila!
C++11 だと取り得る型は全部記述する必要がありますのでちょっとめんどいです.
C++14 だと, マッチしなかったのは auto にしたのに fallback してくれます(ただし, float -> double などの implicit cast に注意! )
その他
mapbox variant では .match
があります.
ただインターフェイスが std::variant
とは異るので使いづらいときもあります.
(将来的に C++17 に移行するときに書き直しが必要)
問題
やっぱりそこそこコンパイルに時間かかるようになってしまいます...
TODO
-
C++14 にもなると
auto
とか...
の嵐でテンプレートの仕組みがよくわからなくなりつらい(デバッグがめんどい)ので理解する