#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
Nie kompiluje: 'return': cannot convert from 'std::optional<int>' to 'bool'
Odniesienie do konsultacji Chciałbym znaleźć wyjaśnienie, ale przeczytałem je tak, jak powinno być dobrze.
Konwersje niejawne są wykonywane za każdym razem, gdy wyrażenie pewnego typu T1 jest używane w kontekście, który nie akceptuje tego typu, ale akceptuje niektóre inne typy T2; w szczególności:
- gdy wyrażenie jest używane jako argument podczas wywoływania funkcji zadeklarowanej za pomocą T2 jako parametru;
- gdy wyrażenie jest używane jako operand z operatorem, który oczekuje T2;
- podczas inicjowania nowego obiektu typu T2, w tym instrukcji return w funkcji zwracającej T2;
- gdy wyrażenie jest używane w instrukcji switch (T2 jest typem integralnym);
- gdy wyrażenie jest używane w instrukcji if lub w pętli (T2 to bool).
operator bool()
ostd::optional
toexplicit
.Odpowiedzi:
std::optional
nie ma możliwości niejawnej konwersji nabool
. (Zezwalanie na niejawne konwersjebool
jest ogólnie uważane za zły pomysł, ponieważbool
jest to typ integralny, więc coś w rodzajuint i = opt
skompilowałoby się i zrobiłoby całkowicie niewłaściwą rzecz).std::optional
nie mają „kontekstowe” do konwersji Bool, definicja, która wygląda podobnie do operatora Obsada:explicit operator bool()
. Nie można tego użyć do niejawnych konwersji; ma zastosowanie tylko w niektórych szczególnych sytuacjach, w których oczekiwany „kontekst” jest wartością logiczną, jak warunek instrukcji if.To czego chcesz
opt.has_value()
.źródło
Z dokumentów C ++ :
Przeczytaj o konwersjach kontekstowych tutaj :
Możesz wykonać następujący hack:
ponieważ konwersja kontekstowa ma miejsce w przypadku wbudowanych operatorów logicznych, ale konwersja kontekstowa nie zawiera
return
instrukcji istd::optional
sama w sobie nie ma niejawnej konwersji nabool
.Dlatego najlepiej byłoby użyć
std::optional<T>::has_value
:źródło
return {opt}
? lubreturn bool{opt};
return {opt};
nie będzie działać, alereturn static_cast<bool>(opt);
czyreturn bool{opt};
będzie działać. Sugeruje się jednak użyciehas_value
funkcji członka, ponieważ naprawdę pokazuje wyraźną intencję tego, co chcesz zrobićreturn !!pot;
hack (has_value
lepszy)Wynika to z faktu, że niejawna kowalencja std :: opcjonalna do bool nie jest obsługiwana: https://en.cppreference.com/w/cpp/utility/optional/operator_bool
Musisz jawnie przekonwertować na bool jako
bool(opt)
lub po prostu użyjopt.has_value()
zamiast tego.źródło
Tak naprawdę nie chodzi o niejawną konwersję, chodzi o rodzaj inicjalizacji.
To, co opcjonalne, ma jawną funkcję konwersji, tj
Z N4849 [class.conv.fct] / p2
Powyższe oznacza, że w tych przypadkach będzie używana funkcja konwersji: [dcl.init] / p16
Jednak te przypadki nie będą korzystać z funkcji konwersji: [dcl.init] / p15
Przykład w pytaniu dotyczy przypadku inicjalizacji kopii i nie wykorzystuje opcjonalnej funkcji konwersji.
źródło