2017-02-24 100 views
2

我有一個派生自boost::variant<T, E>的類型。我做了以下,我不能使用複製構造函數,我不明白爲什麼,一些SFINAE似乎失敗。看起來boost::variant<T, E>構造在繼承構造函數中將T吞併爲ExpectedResult<T, E>。 我怎樣才能解決它,使其工作和最簡單的解決方案?boost.variant派生類型:不能使用複製構造函數

template <class T, class E> 
class ExpectedResult : boost::variant<T, E> { 
public: 
    using boost::variant<T, E>::variant; 
}; 

ExpectedResult<int,float> er; 
ExpectedResult<int, float> er2 = er; 


error: no type named 'type' in 'boost::enable_if<boost::mpl::and_<boost::mpl::not_<boost::is_same<Emotiv::Cortex::Utilities::ExpectedResult<int, float>, boost::variant<int, float> > >, boost::detail::variant::is_variant_constructible_from<const Emotiv::Cortex::Utilities::ExpectedResult<int, float> &, boost::mpl::l_item<mpl_::long_<2>, int, boost::mpl::l_item<mpl_::long_<1>, float, boost::mpl::l_end> > >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, void>'; 'enable_if' cannot be used to disable this declaration 
     typename boost::enable_if<mpl::and_< 
            ^~~~~~~~~~ 
note: in instantiation of member function 'boost::variant<int, float>::variant' requested here 
    using boost::variant<T, E>::variant; 
    while substituting deduced template arguments into function template 'ExpectedResult' [with T = Emotiv::Cortex::Utilities::ExpectedResult<int, float>] 
    ExpectedResult<int, float> er2 = er; 

回答

4

Boost變體有一個完美的轉發構造函數。

您正在將它導入到您的班級中。

它通過檢查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,並將其爆炸。

我會注意添加我自己完美的轉發構造函數以及使用父構造函數,作爲規則如何以可能破壞的方式在C++ 17中如何改變這些變化。由於C++ 17中的重大更改,我目前對使用繼承的構造函數非常不滿,至今我還沒有完全理解。

另一種方法是避免繼承構造,而是轉向變體。

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

相關問題