3
我在整個項目中都使用boost-variant
。在一種情況下,我需要將包含在我的boost-variant
中的類型分爲幾類。由於我的變體中有很多類型,我想到了在訪問者中定義幾個變體的想法。這些變體基本上是type-> class映射。使用訪問者的Boost變體中的分類類型無法編譯
下面的代碼說明了我想達到的目的。
#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
結束。用這個參數來調用這個類型的對象有不同的可能性嗎?它可能是三個operator()
函數之一。
但基本上,我可以將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