boost.variant派生类型:不能使用复制构造函数

问题描述:

我有一个派生自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; 

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