2017-11-24 3 views
4

이 예 emplace가 변형 무가치하게시킨 것을 의미이 예제에서는 std :: variant가 valueless_by_exception이되는 방식은 무엇입니까?

진정한 I 그것이

거짓 출력하려고 한 컴파일러 들어 cppreference

struct S { 
    operator int() { throw 42; } 
}; 


int main(){ 
    variant<float, int> v{12.f}; // OK 
    cout << std::boolalpha << v.valueless_by_exception() << "\n"; 
    try{ 
     v.emplace<1>(S()); // v may be valueless 
    } 
    catch(...){ 
    } 
    cout << std::boolalpha << v.valueless_by_exception() << "\n"; 
} 

에서 예 영감

내가 이해할 수없는 것은 이런 일이 일어난 방법입니다. 특히 emplace이 호출 된 이유를 이해할 수 없다. S에서 int 인수로 변환 한 이후로 프로그램을 호출하지 않을 것으로 기대한다.

+2

변환은'main'이 아닌'emplace' 함수 안에서 발생합니다. – Jarod42

답변

5

주 관련 std::variant::emplace 과부하에 대한 서명 : 그것은 전달 참조의 팩을한다

template <size_t I, class... Args> 
std::variant_alternative_t<I, variant>& emplace(Args&&... args); 

. 즉, 변환 연산자는 S에서 int까지 함수 인수를 평가할 때 호출되지 않습니다. 그것은 emplace의 몸 안쪽이라고합니다. int을 제자리에 만들려고 시도하는 것이 실패 할 것이기 때문에 변형은 예외없이 무 가치가됩니다.

쉽게 이동할 수있는 유형의 경우 이전 값이 저장되기 전에 저장되고 실패하면 복원 될 수 있도록 variant을 구현하는 것이 가능할 수 있습니다. 표준에 의해 주어진 유형의 구현에 대한 다양한 제한 사항.

+1

디자인에 관한 결정은 https://cbeck88.github.io/strict-variant/strict_variant/overview/design.html – NoSenseEtAl

+0

에 대한 좋은 링크입니다. "유형에 대한 다양한 제한 사항에 부합되는지 잘 모르겠습니다. 구현 표준에 의해 주어진. " 나는 리브 리플렉터들에게이 설명이 왜 "emplace"라는 말씨가 초기화가 던지면 "* 값을 가질 수 없다"라고 말하는 이유를 설명하기 위해 들었다. 그러나 나는 힘든 시간을 읽고있다. "현재 포함 된 값을 파괴한다. 'valueless_by_exception()'이'false' 인 경우. " as "는 현재 포함 된 값의 복사본을 나중에 예외의 'variant'에 ​​다시 삽입합니다." – Casey

+2

부스트는 절대로 빈 보증을하지 않습니다 ...이 경우 boost :: variant는 이전에'float' 값을 저장하지 않을 것입니다. 왜냐하면 다시 복사/이동할 수 있기 때문입니다. 'noexcept'로 값을 복원 할 수있는 드문 경우에는 힙 할당과 "이중 버퍼링"을 사용합니다. 'valueless_by_exception'은 퍼포먼스상의 이유와'boost :: variant'의 실패 모드가 매우 놀랄 수 있기 때문에'std :: variant'에 ​​대해 선택되었습니다. –

관련 문제