Рассмотрим следующий код:
#include <iostream>
class first
{
public:
constexpr first(bool val) noexcept : _value{val} {}
constexpr operator bool() const noexcept {return _value;}
private:
bool _value;
};
class second
{
public:
constexpr second(first val) noexcept : _value{val} {}
constexpr operator first() const noexcept {return _value;}
private:
first _value;
};
int main(int argc, char** argv)
{
first f{false};
second s{true};
bool b1 = f;
bool b2 = s; // Not compiling
return 0;
}
До недавнего времени я думал, что стандарт и компиляторы достаточно «умны», чтобы найти требуемую последовательность преобразования, когда она существует.
Другими словами, я думал, что bool b2 = s
будет конвертировать s
в first
и затем bool
, Но, видимо, этого не происходит.
Каков правильный подход для получения эквивалентного поведения для first
а также second
?
Это невозможно, потому что разрешено только одно пользовательское преобразование:
4 Стандартные преобразования [конв]
7 [Примечание: для типов классов пользовательские преобразования рассматриваются как
Что ж; см. 12.3. Как правило, неявная последовательность преобразования (13.3.3.1)
состоит из стандартной последовательности преобразования, за которой следует определенный пользователем
преобразование, сопровождаемое другой стандартной последовательностью преобразования. — конец
нота ]
так же как
12.3 Преобразования [class.conv]
4 Не более одного пользовательского преобразования (конструктор или функция преобразования) неявно применяется к одному
значение.
См. Также пункты 5 (С осторожностью относитесь к пользовательским функциям преобразования), 28 (умные указатели) и 30 (прокси-классы) из более эффективного C ++.
Для стандартных преобразований (с использованием встроенных типов) нет ограничений на количество преобразований в последовательности.
Вам нужно будет добавить operator bool
в second
, Компилятор будет смотреть только на одно пользовательское неявное преобразование.