2016-07-15 14 views
0

boost :: variantを基本値と比較する方法を見つけようとしています。質問は "main()"関数のコメントに定義されています 補助的な質問は、コードで定義されている比較演算子に関するものです。比較演算子の数を減らすには? boost :: variantに6種類の異なる型が含まれている場合、6を定義する必要があります。演算子は2つの亜種を比較することができる?boost :: variantと含まれる値の比較

ありがとうございます!

#include <boost/variant.hpp> 
namespace test { 

    namespace Tag { 
     struct Level1{ int t{ 1 }; }; 
     struct Level2{ int t{ 2 }; }; 
    } 

    template <typename Kind> struct Node; 

    using LevelOne = Node<Tag::Level1>; 
    using LevelTwo = Node<Tag::Level2>; 

    using VariantNode = boost::variant 
    < 
     boost::recursive_wrapper<LevelOne>, 
     boost::recursive_wrapper<LevelTwo> 
    >; 

    typedef VariantNode* pTree; 
    typedef std::vector<pTree> lstTree; 

    template <typename Kind> struct Node 
    { 
     Node(pTree p, std::string n) : parent(p), name(n) {} 
     Node(const Node& another) : name(another.name), parent(another.parent) {} 
     virtual ~Node() {} 
     std::string name; 
     pTree parent; 
    }; 

    bool operator == (const LevelOne& one, const LevelTwo& two) { 
     return false; 
    } 
    bool operator == (const LevelTwo& two, const LevelOne& one) { 
     return false; 
    } 
    bool operator == (const LevelOne& one, const LevelOne& two) { 
     return true; 
    } 
    bool operator == (const LevelTwo& one, const LevelTwo& two) { 
     return true; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    using namespace test; 
    LevelOne l1(nullptr, "level one"); 
    VariantNode tl2 = VariantNode(LevelTwo(nullptr, "level two")); 
    VariantNode tl1 = VariantNode(LevelOne(nullptr, "level one")); 
    bool rv = (tl1 == tl2); // this line compiles OK (comparing two variants) 
    // comparison below does not compile, because "l1" is not a variant. 
    // Question: How can I compare "variant" value "tl1" 
    // with one of the possible content values "l1" 
    bool rv1 = (tl1 == l1); 
    return 1; 
} 
+0

あなた 'ブール演算子==(...)は'テンプレートすることができます。実際には、カスタムテンプレートマジックは必要ありません。 'std :: is_same :: value'を返すだけです。 – lorro

+0

@lorro - ありがとう!比較は次のように定義されています。 テンプレート bool演算子==(const F&f、const S&s){ \t \t bool issame = std :: is_same :: value; \t \t if(!issame) \t \t \t falseを返します。 \t \t return f.name == s.name; \t} 残りの質問 - この値からバリアントを構築することなく、boost :: variantを基礎値とどのように比較するのですか? –

+0

'get <>()'を使用してください(私があなたを得た場合)。 boost :: get <>を使用するには – lorro

答えて

2

以下は、バリアント内の型の任意の数で動作します:

template<typename T> 
struct equality_visitor : boost::static_visitor<bool> { 
    explicit constexpr equality_visitor(T t) : t_(std::move(t)) { } 

    template<typename U, std::enable_if_t<std::is_same<T, U>::value>* = nullptr> 
    constexpr bool operator()(U const& u) const { 
     return t_ == u; 
    } 

    template<typename U, std::enable_if_t<!std::is_same<T, U>::value>* = nullptr> 
    constexpr bool operator()(U const&) const { 
     return false; 
    } 

private: 
    T t_; 
}; 

template< 
    typename T, 
    typename... Ts, 
    typename = std::enable_if_t< 
     boost::mpl::contains<typename boost::variant<Ts...>::types, T>::value 
    > 
> 
constexpr bool operator ==(T const& t, boost::variant<Ts...> const& v) { 
    equality_visitor<T> ev{t}; 
    return v.apply_visitor(ev); 
} 

template< 
    typename T, 
    typename... Ts, 
    typename = std::enable_if_t< 
     boost::mpl::contains<typename boost::variant<Ts...>::types, T>::value 
    > 
> 
constexpr bool operator !=(T const& t, boost::variant<Ts...> const& v) { 
    return !(t == v); 
} 

キャッチ比較は常にむしろvariant == valueまたはvariant != valueよりもフォームvalue == variantまたはvalue != variantのものでなければならないということです。これはboost::variant<>自体がこれらの演算子を常にstatic_assertと定義しており、variant<>の組み込み演算子よりもさらにグローバルな演算子を作成する方法がないためです。

Online Demo

+0

@lidjarn - ありがとう!これはvs2013でコンパイルされ、実行されます(constexprなし)。バリデーショナルテンプレートでは動作しませんでしたので、コードを勉強しています。大きな助け! –

関連する問題