私のプロジェクトではboost-variant
を使用しています。 1つのシナリオでは、私はboost-variant
に含まれる型をいくつかのクラスに分類する必要があります。私のバリアントにはかなり多くのタイプがあるので、私は訪問者の中にいくつかのバリアントを定義するという考えに至りました。これらの変種は基本的に型 - >クラスのマッピングです。ビジターを使用したブーストバリアントのタイプはコンパイルされません
以下のコードは、私が達成したいことを示しています。
#include <iostream>
#include <boost/variant.hpp>
#include <string>
enum class Type {
Integer,
Float,
NonNumeric
};
struct IsNum : public boost::static_visitor<Type> {
typedef boost::variant<int, size_t> IntegerTypes;
typedef boost::variant<float, double> FloatTypes;
typedef boost::variant<std::string> NonNumericTypes;
result_type operator()(const IntegerTypes& t) const {
return Type::Integer;
}
result_type operator()(const FloatTypes& t) const {
return Type::Float;
}
result_type operator()(const NonNumericTypes& t) const {
return Type::NonNumeric;
}
};
int main() {
boost::variant<int, std::string, double> value;
value = 5;
IsNum visitor;
auto result = value.apply_visitor(visitor);
}
残念ながら、コードはコンパイルされません。 MSVCは、コンパイラエラーC3066
で終了します。この引数を使ってこの型のオブジェクトを呼び出す方法はいくつかあります。それは3つのoperator()
関数の1つかもしれません。
しかし、基本的に私は5をバリアントタイプIntegerTypes
にのみ変換することができます。
この種の問題の解決方法はありますか?私は、このソリューションに到着boost-mpl
を使用しようとした後
独自のソリューション
。機能Contains
は、私のプログラムの他の部分に含まれる再利用可能なソフトウェアを表しています。それでも私のオリジナルの投稿されたソースコードに近いソリューションを望んでいました。
#include <iostream>
#include <boost/variant.hpp>
#include <string>
#include <boost/mpl/contains.hpp>
enum class Type {
Integer,
Float,
NonNumeric
};
template<typename V, typename T>
using ContainsImpl = typename boost::mpl::contains<typename V::types, T>::type;
template<typename V, typename T>
bool Contains(const T&) {
return ContainsImpl<V, T>::value;
}
struct IsNum : public boost::static_visitor<Type> {
typedef boost::variant<int, size_t> IntegerTypes;
typedef boost::variant<float, double> FloatTypes;
typedef boost::variant<std::string> NonNumericTypes;
template<typename T>
result_type operator()(const T& t) const {
if (Contains<IntegerTypes>(t)) {
return Type::Integer;
} else if (Contains<FloatTypes>(t)) {
return Type::Float;
} else if (Contains<NonNumericTypes>(t)) {
return Type::NonNumeric;
}
return Type::NonNumeric;
}
};
int main() {
boost::variant<int, std::string, double> value;
value = 5.;
IsNum visitor;
auto result = value.apply_visitor(visitor);
if (result == Type::Integer) {
std::cout << "Integer" << std::endl;
}
if (result == Type::Float) {
std::cout << "Float" << std::endl;
}
if (result == Type::NonNumeric) {
std::cout << "Non Numeric" << std::endl;
}
}
クール。私は今この解決法を導き出しました。唯一の実行可能なアプローチだと思われます。しかし、それを読んで頭がおかしくなるかもしれません。私の解決策も投稿します。どうもありがとう。 – Aleph0
@FrankSimonより多くの選択肢には次のものがあります。タグのディスパッチと各タイプの個別のオーバーロードの追加 –
タグディスパッチが何であるか分かりません。私はもう少し勉強しなければならないと思います。 :-) – Aleph0