반환시 암시 적 변환은 허용되지 않습니다.


21
#include <optional>

bool f() {
  std::optional<int> opt;
  return opt;
}

컴파일하지 않습니다 : 'return': cannot convert from 'std::optional<int>' to 'bool'

컨설팅 참조 설명을 찾아야한다고 생각했지만 괜찮 았으므로 읽었습니다.

일부 유형 T1의 표현식이 해당 유형을 허용하지 않지만 다른 유형 T2를 허용하는 컨텍스트에서 사용될 때마다 내재적 변환이 수행됩니다. 특히:

  • T2를 매개 변수로 선언 한 함수를 호출 할 때 표현식이 인수로 사용될 때;
  • T2를 기대하는 연산자와 함께 피연산자로 표현식이 사용될 때;
  • T2를 반환하는 함수에 return 문을 포함하여 T2 유형의 새 객체를 초기화 할 때;
  • 표현식이 스위치 명령문에서 사용될 때 (T2는 정수 유형);
  • 표현식이 if 문이나 루프에서 사용될 때 (T2는 bool)

7
" 암시 적 변환이 수행됩니다" 하지만 operator bool()의는 std::optional있다 explicit.
Jarod42

답변:


22

std::optional으로 암시 적으로 변환 할 수있는 기능이 없습니다 bool. (암시 적 변환을 허용하는 bool것은 일반적으로 나쁜 생각으로 간주됩니다. bool통합 유형이므로 int i = opt컴파일하고 잘못된 일을 완전히 수행하기 때문입니다.)

std::optional 않는 bool에있는 "상황에 맞는 변환"가,의 정의는 캐스트 연산자과 유사합니다 explicit operator bool(). 암시 적 변환에는 사용할 수 없습니다. 예상되는 "문맥"이 if 문의 조건과 같은 부울 인 특정 상황에서만 적용됩니다.

당신이 원하는 것은 opt.has_value()입니다.


4

C ++ 문서에서 :

optional <T> 유형의 객체 가 문맥 상 bool로 변환 될 때 객체에 값이 있으면 true를 반환하고 값이 없으면 false를 반환합니다.

상황 별 전환에 대한 내용은 여기를 참조하십시오 .

다음과 같은 맥락에서, bool 유형이 예상되며 선언이 bool t (e)이면 암시 적 변환이 수행됩니다. 잘 구성되어 있습니다 (즉, 명시 적 T :: operator bool () const와 같은 명시 적 변환 함수가 고려 됨). 이러한 표현 e는 상황에 따라 부울로 변환된다고한다.

  • if의 제어 표현;
  • 내장 논리 연산자의 피연산자!, && 및 ||;
  • 조건부 연산자의 첫 번째 피연산자? :;
  • static_assert 선언의 술어;
  • noexcept 지정자에서의 표현;
  • 명시 적 지정자의 표현;

다음과 같은 해킹을 수행 할 수 있습니다.

bool f() {
    std::optional<int> opt;
    return opt || false;
}

문맥 전환 않는 논리 연산자 내장 있지만, 문맥 전환의 경우에 발생하기 때문에 하지 포함 return문을과 std::optional에 의해 자체가 않습니다 하지 에 암시 적 변환이 bool.

따라서 다음을 사용하는 것이 가장 좋습니다 std::optional<T>::has_value.

bool f() {
    std::optional<int> opt;
    return opt.has_value();
}

무엇에 대해 return {opt}? 또는return bool{opt};
darune

3
@darune은 return {opt};작동하지만,하지 않을 것이다 return static_cast<bool>(opt);또는return bool{opt}; 작동합니다. 그러나, 사용하는 것이 좋습니다 has_value정말 당신이 원하는 무엇의 명확한 의도를 보여주기 때문에 멤버 함수를
호두 까기 인형

또는 유명한 return !!pot;핵 ( has_value낫다)
LF


1

이것은 실제로 암시 적 변환에 관한 것이 아니라 초기화 유형에 관한 것입니다.

선택적인 것은 명시적인 변환 함수입니다.

explicit operator bool() const; 

N4849부터 [class.conv.fct] / p2

변환 함수는 명시 적 (9.2.2) 일 수 있으며,이 경우 직접 초기화를위한 사용자 정의 변환으로 만 간주됩니다.

위의 경우 이러한 경우 변환 기능을 사용합니다. [dcl.init] / p16

괄호로 묶인 expression-list 또는 braced-init-list 인 이니셜 라이저 (16.1) — new_initializer (7.6.2.7), (16.3)의 static_cast 표현식에서 발생하는 초기화 (16.1) 7.6.1.8), (16.4)-기능 표기법 유형 변환 (7.6.1.3) 및 (16.5)-조건의 괄호로 묶인 초기 목록 형식을 직접 초기화라고합니다.

그러나 이러한 경우 변환 기능을 사용하지 않습니다. [dcl.init] / p15

인수 전달, 함수 반환, 예외 발생 (14.2), 예외 처리 (14.4) 및 멤버 초기화뿐만 아니라 괄호 또는 같음 초기화 기 또는 조건 (8.5)의 = 형식으로 발생하는 초기화 (9.4.1)을 복사 초기화라고합니다.

문제의 예는 복사 초기화 사례에 해당하며 선택 사항의 변환 기능을 사용하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.