Короткий
Функція перетворення operator int()
вибирається clang over, operator bool() const
оскільки b
не є const, тоді як оператор перетворення для bool є.
Короткі міркування полягають у тому, що кандидат функціонує для дозволу перевантаження (із наявним неявним параметром об’єкта) під час перетворення b
на bool
є
operator bool (B2 const &);
operator int (B2 &);
де другий - кращий матч, оскільки b
не відповідає кваліфікації.
Якщо обидві функції мають однакову кваліфікацію (обидві const
чи ні), operator bool
вибрано, оскільки вона забезпечує пряме перетворення.
Перетворення за допомогою нотації, аналізується поетапно
Якщо ми погодимось, що логічний вставки ostream (std :: basic_ostream :: operator << (bool val) згідно [ostream.inserters.arithmetic]) викликається зі значенням, яке є результатом перетворення b
на, bool
ми можемо скопатися в цьому перетворенні .
1. Акторський вираз
Акторський склад `` b ''
(bool)b
оцінює до
static_cast<bool>(b)
відповідно до C ++ 11, 5.4 / 4 [expr.cast], оскільки const_cast
не застосовується (тут не додавання або видалення const).
Це статичне перетворення допускається за C ++ 11, 5.2.9 / 4 [expr.static.cast] , якщо bool t(b);
для винайденої змінної t добре сформовано. Такі оператори називаються прямою ініціалізацією відповідно до C ++ 11, 8.5 / 15 [dcl.init] .
2. Пряма ініціалізація bool t(b);
Пункт 16 найменш згаданого стандартного абзацу говорить (наголошую на моєму):
Семантика ініціалізаторів така. Тип призначення - це тип об’єкта або посилання, що ініціалізується, а тип джерела - тип виразу ініціалізатора.
[...]
[...] якщо тип джерела є типом класу (можливо, відповідає стандарту cv) , розглядаються функції перетворення .
Перелічені відповідні функції перетворення, і найкраща з них вибирається за допомогою дозволу перевантаження.
2.1 Які функції перетворення доступні?
Доступні функції перетворення є, operator int ()
і operator bool() const
оскільки, як говорить C ++ 11, 12.3 / 5 [class.conv] :
Функція перетворення в похідному класі не приховує функції перетворення в базовому класі, якщо ці дві функції не перетворюються на один і той же тип.
Хоча C ++ 11, 13.3.1.5/1 [over.match.conv] говорить:
Розглянуто функції перетворення S та його базових класів.
де S - клас, з якого буде перетворено.
2.2 Які функції перетворення застосовні?
C ++ 11, 13.3.1.5/1 [over.match.conv] (курсив мій):
1 [...] Припускаючи, що “cv1 T” - це тип об’єкта, який ініціалізується, а “cv S” - тип виразу ініціалізатора, при цьому тип класу S, функції-кандидати вибираються наступним чином: Перетворення розглядаються функції S та його базових класів. Ті невідверті функції перетворення, які не приховані в S і дають тип T або тип, який можна перетворити в тип T за допомогою стандартної послідовності перетворення, є функціями-кандидатами.
Тому operator bool () const
застосовується, оскільки він не прихований всередині B2
і дає a bool
.
Частина з наголосом в останній стандартній цитаті є релевантною для перетворення з використанням, operator int ()
оскільки int
це тип, який можна перетворити на bool за допомогою стандартної послідовності перетворення. Перетворення з int
у bool
є навіть не послідовністю, а простим прямим перетворенням, яке дозволено на C ++ 11, 4.12 / 1 [conv.bool]
Перше значення арифметики, неперерахованого перерахування, покажчик або покажчик на тип члена може бути перетворено на перше значення типу bool. Нульове значення, значення нульового покажчика або значення покажчика нульового члена перетворюється на false; будь-яке інше значення перетворюється на істинне.
Це означає, що operator int ()
це також застосовується.
2.3 Яка функція перетворення обрана?
Вибір відповідної функції перетворення здійснюється за допомогою дозволу перевантаження ( C ++ 11, 13.3.1.5/1 [over.match.conv] ):
Роздільна здатність перевантаження використовується для вибору функції перетворення, яку потрібно викликати.
Існує одна особлива "химерність", коли справа стосується дозволу перевантаження для функцій члена класу: неявний параметр об'єкта ".
За C ++ 11, 13.3.1 [over.match.funcs] ,
[...] як статичні, так і нестатичні функції-члени мають неявний параметр об’єкта [...]
де тип цього параметра для нестатичних функцій-членів - згідно з пунктом 4-:
“Посилання на значення cv X” для функцій, оголошених без кваліфікатора ref або з кваліфікатором & ref
“Посилання rvalue на cv X” для функцій, оголошених за допомогою && ref-кваліфікатора
де X - клас, членом якого є функція, а cv - кваліфікація cv у оголошенні функції-члена.
Це означає, що (згідно C ++ 11, 13.3.1.5/2 [over.match.conv] ), при ініціалізації функцією перетворення,
[t] Список аргументів має один аргумент, який є виразом ініціалізатора. [Примітка: Цей аргумент буде порівняно з неявним параметром об’єкта функцій перетворення. —Кінець примітки]
Функціями-кандидатами для вирішення перевантаження є:
operator bool (B2 const &);
operator int (B2 &);
Очевидно, operator int ()
що кращий збіг, якщо перетворення запитується з використанням непостійного об’єкта типу, B2
оскільки operator bool ()
потрібно кваліфікаційне перетворення.
Якщо обидві функції перетворення мають однакову кваліфікацію const, дозвіл на перевантаження цієї функції більше не зробить фокусу. У такому випадку ранжування конверсії (послідовності) стає на місце.
3. Чому operator bool ()
вибрано, коли обидві функції перетворення мають однакову кваліфікацію const?
Перетворення з B2
у bool
є визначеною користувачем послідовністю перетворення ( C ++ 11, 13.3.3.1.2 / 1 [over.ics.user] )
Визначена користувачем послідовність перетворення складається з початкової стандартної послідовності перетворення, за якою слідує перетворення, визначене користувачем, за яким слід друга стандартна послідовність перетворення.
[...] Якщо визначена користувачем перетворення задається функцією перетворення, початкова стандартна послідовність перетворення перетворює тип джерела на неявний параметр об’єкта функції перетворення.
C ++ 11, 13.3.3.2/3 [over.ics.rank]
[...] визначає часткове впорядкування неявних послідовностей перетворень на основі взаємозв’язків кращої послідовності перетворення та кращого перетворення.
... друга стандартна послідовність перетворення U2.
Друге стандартне перетворення є випадком operator bool()
is bool
до bool
(перетворення ідентичності), тоді як друге стандартне перетворення у випадку operator int ()
є, int
до bool
якого є булевим перетворенням.
Отже, послідовність перетворення, використовуючи operator bool ()
, є кращою, якщо обидві функції перетворення мають однакову кваліфікацію const.