2017-02-24 13 views
2

boost::variant<T, E>から派生した型があります。私は次のことをして、私はコピーコンストラクタを使用することはできません、私は理由を把握することができない、いくつかSFINAEが失敗するようです。 boost::variant<T, E>構造が継承されたコンストラクタでTExpectedResult<T, E>として飲み込んでいるように見えます。 私はそれを簡単に解決できるように修正できますか?boost.variant派生型:コピーコンストラクタを使用できません

答えて

4

ブーストバリアントには、完全な転送コンストラクタがあります。

あなたのクラスにインポートしています。

selfがちょうどboost::variantであるかどうかをチェックすることにより、self&の消費を防ぎます。あなたはそれをExpectedResult&に渡しています。

これは混乱します。

template <class T, class E> 
struct ExpectedResult : boost::variant<T, E> { 
    using boost::variant<T, E>::variant; 
    ExpectedResult()=default; 
    ExpectedResult(ExpectedResult const&)=default; 
    ExpectedResult(ExpectedResult &&)=default; 
    ExpectedResult(ExpectedResult & o): 
    ExpectedResult(const_cast<ExpectedResult const&>(o)) 
    {} 
    ExpectedResult(ExpectedResult &&)=default; 
    ExpectedResult(ExpectedResult const&& o): 
    ExpectedResult(o) // calls const& ctor 
    {} 
    ExpectedResult& operator=(ExpectedResult const&)=default; 
    ExpectedResult& operator=(ExpectedResult &&)=default; 
    ExpectedResult& operator=(ExpectedResult &) { 
    return *this=const_cast<ExpectedResult const&>(o); 
    } 
    ExpectedResult& operator=(ExpectedResult const&& o){ 
    return *this = o; // const& assign 
    } 
}; 

上記の既定の手作業で作成された特別なメンバー関数が役立つと思われます。

さらに、volatileを追加して別の束で爆発させる必要があります。

私は自分自身の完璧な転送コンストラクタと親コンストラクタを使うことに注意しています。私は現在、継承されたコンストラクタを使用することについて非常に心配しています。なぜなら、私はまだ完全に理解していません。

もう1つのアプローチは、継承を回避し、代わりにバリアントに進むことです。

template <class T, class E> 
struct ExpectedResult : boost::variant<T, E> { 
    using base=boost::variant<T, E>; 
    ExpectedResult()=default; 
    ExpectedResult(ExpectedResult const&)=default; 
    ExpectedResult(ExpectedResult &&)=default; 
    ExpectedResult(ExpectedResult &&)=default; 
    ExpectedResult& operator=(ExpectedResult const&)=default; 
    ExpectedResult& operator=(ExpectedResult &&)=default; 

    template<class T0, class...Ts, 
    class=std::enable_if_t< 
     std::is_constructible<base, T0, Ts...>::value 
     && (
     (sizeof...(ts)!=0) 
     || !std::is_same<std::decay_t<T0>, ExpectedResult>::value 
    )   
    > 
    > 
    ExpectedResult(T0&&t0, Ts&&...ts): 
    base(std::forward<T0>(t0), std::forward<Ts>(ts)...) 
    {} 
}; 

完全に不完全な状態では完全に転送されますが、ほとんどの場合は十分に近い状態です。

initializer_list<T>, Ts&&...コンストラクタは完璧な転送をより完全に行うことができるため、ExpectedResult<std::vector<int>, bool> er{ {1,2,3,4} }が動作します。

+0

ガード動作をバグと見なすべきでしょうか?私は必要なすべての複製を過度に見つけます。多分私はバグを提出するべきです。 –

+2

@GermánDiagoタイプはおそらく継承されるようには設計されていません。しかし、is_sameをis_base_ofに変更して、あなたのケースでうまく動作させる可能性があります。それが他の問題を引き起こすかどうかはわかりません... – Yakk

関連する問題