C++ (Qt)#include <iostream>#include <boost/variant.hpp> template <class T>struct numeric_visitor : public boost::static_visitor<T>{ T operator()(int val) const { return val; } T operator()(float val) const { return val; } T operator()(double val) const { return val; } template <class S> T operator()(S) const { return T(); } // или кидаем исключение..}; template <class T>struct string_visitor : public boost::static_visitor<T>{ T operator()(const std::string& val) const { return val; } template <class S> T operator()(S) const { return T(); } // или кидаем исключение}; struct numeric_category : public boost::static_visitor<bool>{ bool operator()(double) const { return true; } bool operator()(float) const { return true; } bool operator()(int) const { return true; } template <class T> bool operator()(T) const { return false; } }; struct string_category : public boost::static_visitor<bool>{ bool operator()(std::string) const { return true; } template <class T> bool operator()(T) const { return false; }}; template <class V>bool is_numeric(V v){ return boost::apply_visitor(numeric_category(), v);} template <class V>bool is_string(V v){ return boost::apply_visitor(string_category(), v);} int main(){ typedef boost::variant<double, float, int, std::string> variant_t; variant_t v1 = 1.1234; // 10; 1.234f ... variant_t v2 = std::string("abc"); if (is_numeric(v1)) std::cout << "numeric: val = " << boost::apply_visitor(numeric_visitor<double>(), v1) << std::endl; if (is_string(v2)) std::cout << "string: val = " << boost::apply_visitor(string_visitor<std::string>(), v2) << std::endl; return 0;}
C++ (Qt)#include <iostream>#include <variant.h>#include <string>#include <boost/optional.hpp> typedef variant<float, double, int, std::string> variant_t; int main(){ variant_visitor<boost::optional<double> (variant_t)> is_numeric; is_numeric.reg<double>([](variant_t v) { return v.get<double>(); }); is_numeric.reg<int>([](variant_t v) { return v.get<int>(); }); is_numeric.reg<float>([](variant_t v) { return v.get<float>(); }); variant_visitor<boost::optional<std::string> (variant_t)> is_string; is_string.reg<std::string>([](variant_t v) { return v.get<std::string>(); }); variant_t v = 123.676; variant_t v2 = std::string("abc"); if (is_numeric(v)) std::cout << *is_numeric(v) << std::endl; if (is_string(v2)) std::cout << *is_string(v2) << std::endl; return 0;}
C++ (Qt)#include <iostream>#include <string>#include <boost/optional.hpp>#include <boost/variant.hpp> typedef boost::variant<float, double, int, std::string> variant_t; struct is_numeric : public boost::static_visitor<boost::optional<double>>{ result_type operator()(float v) const { return v; } result_type operator()(double v) const { return v; } result_type operator()(int v) const { return v; } template <class R> result_type operator()(R) const { return result_type(); }}; struct is_string : public boost::static_visitor<boost::optional<std::string>>{ result_type operator()(const std::string & v) const { return v; } template <class R> result_type operator()(R) const { return result_type(); }}; int main(){ variant_t v = 123; if (boost::apply_visitor(is_numeric(), v)) std::cout << *boost::apply_visitor(is_numeric(), v) << std::endl; if (boost::apply_visitor(is_string(), v)) std::cout << *boost::apply_visitor(is_string(), v) << std::endl; return 0;}
C++ (Qt)variant_visitor<boost::optional<double> (variant_t)> is_numeric; is_numeric.reg<double>([](variant_t v) { return v.get<double>(); }); is_numeric.reg<int>([](variant_t v) { return v.get<int>(); }); is_numeric.reg<float>([](variant_t v) { return v.get<float>(); }); is_numeric.reg<std::string>([](variant_t v)->boost::optional<double> { try { return std::stod(v.get<std::string>()); } catch (...) { return boost::optional<double>(); } } ); std::list<variant_t> list; list.push_back(1); list.push_back(123.456); list.push_back(std::string("abc")); list.push_back(std::string("6483.238578")); list.sort([&](variant_t v1, variant_t v2)->bool { auto x = is_numeric(v1); auto y = is_numeric(v2); return (x && y) ? (*x < *y) : (x && !y); });
C++ (Qt)#include <iostream>#include <string>#include <vector> struct MyStruct { MyStruct( int val = 0 ) : mUseText(false), mVal(val) {} MyStruct( const char * str ) : mUseText(true), mStr(str) {} bool operator < ( const MyStruct & sec ) const { if (mUseText || sec.mUseText) return false; // wrong return mVal < sec.mVal; } // data bool mUseText; union { int mVal; const char * mStr; };}; int main( void ){ std::vector <MyStruct> vec; vec.push_back(MyStruct("str1")); vec.push_back(MyStruct(5)); vec.push_back(MyStruct(2)); vec.push_back(MyStruct("str2")); vec.push_back(MyStruct(1)); vec.push_back(MyStruct("str3")); std::sort(vec.begin(), vec.end()); for (size_t i = 0; i < vec.size(); ++i) if (vec[i].mUseText) std::cout << vec[i].mStr << std::endl; else std::cout << vec[i].mVal << std::endl; return 0;}
C++ (Qt)struct MyStruct { MyStruct( int val = 0 ) : mUseText(false), mVal(val) {} MyStruct( const char * str ) : mUseText(true), mStr(str) {} bool operator < ( const MyStruct & sec ) const { return toInt() < sec.toInt(); } int toInt() const { return mUseText? std::numeric_limits<int>::max() : mVal; } // data bool mUseText; union { int mVal; const char * mStr; };};
C++ (Qt)typedef boost::variant<float, double, int, long, short, std::string> variant_t; struct numeric : public boost::static_visitor<boost::optional<double>>{ template <class T> result_type operator()(T v) const { return std::is_arithmetic<T>::value ? v : result_type(); } result_type operator()(const std::string & s) const { try { return std::stod(s); } catch (...) { return result_type(); } }};
C++ (Qt)typedef boost::variant<float, double, int, long, short, std::string> variant_t; struct numeric : public boost::static_visitor<boost::optional<double>>{ template <class T> result_type operator()(T v) const { return std::is_arithmetic<T>::value ? v : result_type(); }...};
C++ (Qt)QVariant v(5);if (v.canConvert<double>()) double d = v.toDouble();
C++ (Qt)typedef MyClass<float, double, int, long, short, std::string> ClassNum;
C++ (Qt)void Test( const ClassNum & src ){ double d = src; short s = src; // неясно, а если src не влезет в short? std:::string s = src;// long long l = src; // а этого типа нет для ClassNum}
C++ (Qt)void Test( const ClassNum & src ){ double d = get<double>( src ); short s = get<short>( src ); // Если не будет влазить в short - обрежется, а можно и исключение бросать об этом std::string str = get<std::string>( src ); long long l = get<long long>( src ); // И не важно, что этого типа нет в варианте // или второй вариант get double d; get( d, src ); short s; get( s, src ); long long l; get( l, src );}
C++ (Qt)typedef boost::variant<short, int, long, float, double, std::string> var_t; template<class T>struct numeric : public boost::static_visitor<T>{ template<class V> T operator()( V val ) const { return std::is_arithmetic<V>::value ? val : std::numeric_limits<T>::max(); } T operator()( const std::string &val ) const { try { return boost::lexical_cast<T>( val ); } catch(...) {} return std::numeric_limits<T>::max(); }}; struct literal : public boost::static_visitor<std::string>{ template<class V> std::string operator()( V val ) const { return boost::lexical_cast<std::string>( val ); }}; template<class T>T get( var_t v ){ static_assert( std::is_arithmetic<T>::value, "Shit type T" ); return boost::apply_visitor( numeric<T>(), v );} template<>std::string get<std::string>( var_t v ){ return boost::apply_visitor( literal(), v );} template<class T>void get( T &res, var_t v ){ static_assert( std::is_arithmetic<T>::value, "Shit type T" ); res = boost::apply_visitor( numeric<T>(), v );} int main(){ var_t v1 = 100000; var_t v2 = 200000L; var_t v3 = "300000"; var_t v4 = "test string"; ushort r1 = get<ushort>( v1 ); long r2 = get<long>( v2 ); double r3 = get<double>( v2 ); long long r4 = get<long long>( v1 ); float r5 = get<float>( v3 ); short r6 = get<short>( v3 ); std::string r7 = get<std::string>( v4 ); cout << "r1 (short) = " << r1 << endl << "r2 (long) = " << r2 << endl << "r3 (double) = " << r3 << endl << "r4 (long long) = " << r4 << endl << "r5 (float) = " << r5 << endl << "r6 (short) = " << r6 << endl << "r7 (string) = " << r7 << endl; return 0;}
C++ (Qt) Variant v1 = 10; Variant v2 = v1; // у v2 и v1 теперь общие данные int *a; v1.tryGetValue(a); std::cout << *a << std::endl; (*a) = 123; std::cout << v2.value<int>() << std::endl; // v2 теперь тоже вернёт 123
C++ (Qt)template <typename T> bool tryGetValue(T*& val) { if (!isType<T>()) return false; if (!holder_.unique()) holder_ = std::make_shared<Holder<T>>(typeid(T).name(), std::static_pointer_cast<Holder<T>>(holder_)->value); val = &(std::static_pointer_cast<Holder<T>>(holder_)->value); return true; }