【问题标题】:boost.variant derived type: cannot use copy constructorboost.variant 派生类型:不能使用复制构造函数
【发布时间】:2017-02-24 11:00:29
【问题描述】:

我有一个派生自boost::variant<T, E> 的类型。我做了以下,我不能使用复制构造函数,我不知道为什么,一些SFINAE 似乎失败了。看起来boost::variant<T, E> 构造在继承的构造函数中将T 吞噬为ExpectedResult<T, E>。 我该如何修复它以使其正常工作并使用最简单的解决方案?

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;

【问题讨论】:

    标签: c++ c++11 variant boost-variant


    【解决方案1】:

    Boost 变体有一个完美的转发构造函数。

    您正在将其导入您的班级。

    它通过检查self 是否正好是boost::variant 来防止消费self&amp;。你传递给它一个ExpectedResult&amp;

    这让人困惑。

    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&lt;T&gt;, Ts&amp;&amp;... 构造函数可以使完美转发更加完美,所以ExpectedResult&lt;std::vector&lt;int&gt;, bool&gt; er{ {1,2,3,4} } 可以工作。

    【讨论】:

    • 是否应该将守卫行为视为错误?我发现所有必要的复制都过多。也许我应该提交一个错误。
    • @GermánDiago 该类型可能不是为了继承而设计的;但他们可以将一些 is_same 更改为 is_base_of 以使其适用于您的情况。我不知道这是否会导致其他问题...
    猜你喜欢
    • 1970-01-01
    • 2019-08-07
    • 2013-06-23
    • 1970-01-01
    • 2020-02-28
    • 2011-10-10
    • 1970-01-01
    • 2012-09-28
    • 2018-09-24
    相关资源
    最近更新 更多