2016-06-27 11 views
5

私はブーストバリアント型定義を持っている:ブーストバリアントのプラスアクションを簡略化するにはどうすればよいですか?

typedef boost::variant< bool, int, float, double> VariantType; 

私はそれに追加/減算/乗算/除算アクションを実装したいです。例えばAddクラスを取る。問題は、VariantType(std :: stringなど)に新しいタイプを追加する場合です。Addクラスを新しいタイプで更新する必要があります。

struct Add : public boost::static_visitor<VariantType> { 
    template <typename T> 
    T operator() (T a, T b) const { 
     return a + b; 
    } 
    float operator() (int a, float b) const { 
     return a + b; 
    } 
    float operator() (float a, int b) const { 
     return a + b; 
    } 
    double operator() (int a, double b) const { 
     return a + b; 
    } 
    double operator() (double a, int b) const { 
     return a + b; 
    } 
    double operator() (float a, double b) const { 
     return a + b; 
    } 
    double operator() (double a, float b) const { 
     return a + b; 
    } 
    VariantType operator() (bool a, int b) const { 
     throw std::invalid_argument("bool and int can't Plus"); 
    } 
    VariantType operator() (bool a, float b) const { 
     throw std::invalid_argument("bool and float can't Plus"); 
    } 
    VariantType operator() (bool a, double b) const { 
     throw std::invalid_argument("bool and double can't Plus"); 
    } 
    VariantType operator() (int a, bool b) const { 
     throw std::invalid_argument("int and bool can't Plus"); 
    } 
    VariantType operator() (float a, bool b) const { 
     throw std::invalid_argument("float and bool can't Plus"); 
    } 
    VariantType operator() (double a, bool b) const { 
     throw std::invalid_argument("double and bool can't Plus"); 
    } 
}; 

使用:

VariantType v1 = 1; 
VariantType v2 = 2.1; 
VariantType v3 = boost::apply_visitor(Add(), v1, v2); 
cout<<boost::get<double>(v3)<<endl; //Print 2.2 

GCCのバージョンが4.8.2です。ブーストバージョンは1.57.0です。 Addクラスを簡単にする方法は?ありがとう。

答えて

3

ちょうどそれ多型ファンクタます

Live On Coliru

#include <boost/variant.hpp> 
#include <iostream> 

using VariantType = boost::variant<int, float, double, bool>; 

struct Add : public boost::static_visitor<VariantType> { 
    template <typename T, typename U> 
    auto operator() (T a, U b) const -> decltype(a+b) { return a + b; } 

    template <typename T> VariantType operator()(bool, T) const { throw std::invalid_argument("Can't to bool"); } 
    template <typename T> VariantType operator()(T, bool) const { throw std::invalid_argument("Can't add bool"); } 
    VariantType      operator()(bool,bool) const { throw std::invalid_argument("Can't add bools"); } 
}; 

int main() { 
    std::cout << std::boolalpha; 

    VariantType specimens[] = { int(42), 3.14f, 3.14, true }; 
    for (auto lhs : specimens) 
     for (auto rhs : specimens) 
     { 
      try { 
       std::cout << lhs << " + " << rhs << " == " << boost::apply_visitor(Add{}, lhs, rhs) << "\n"; 
      } catch(std::exception const& e) { 
       std::cout << lhs << " + " << rhs << " ==> " << e.what() << "\n"; 
      } 
     } 
} 

プリント:

42 + 42 == 84 
42 + 3.14 == 45.14 
42 + 3.14 == 45.14 
42 + true ==> Can't add bool 
3.14 + 42 == 45.14 
3.14 + 3.14 == 6.28 
3.14 + 3.14 == 6.28 
3.14 + true ==> Can't add bool 
3.14 + 42 == 45.14 
3.14 + 3.14 == 6.28 
3.14 + 3.14 == 6.28 
3.14 + true ==> Can't add bool 
true + 42 ==> Can't to bool 
true + 3.14 ==> Can't to bool 
true + 3.14 ==> Can't to bool 
true + true ==> Can't add bools 
+0

私は多くの小さな修正/明確化/ CCとの実際の例を追加しました@ DanielSchepler – sehe

+0

それは動作します。ありがとう – liuzw

関連する問題