2017-02-24 9 views
2

boost::variant<T, E>에서 파생 된 형식이 있습니다. 다음 작업을 수행하고 복사 생성자를 사용할 수 없기 때문에 이유를 알아낼 수 없습니다. 일부 SFINAE이 실패한 것으로 보입니다. boost::variant<T, E> 구조가 상속 된 생성자에서 TExpectedResult<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

부스트 변형에는 완벽한 전달 생성자가 있습니다.

클래스로 가져올 수 있습니다.

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