Я нашел кое-что странное поведение в C ++: оператор typecast в частном базовом классе сбивает с толку компилятор при попытке разрешить неявное приведение:
#include <iostream>
struct Base
{
#ifdef ENABLE
operator bool () const { return true; }
#endif
};
struct Derived : private Base
{
operator int () const { return 7; }
};
int main()
{
Derived o;
std::cout << o << '\n';
return 0;
}
Без -DENABLE
, код компилируется просто отлично, и выводит 7
, С -DENABLE
, код больше не компилируется, жалуясь на неоднозначную перегрузку. Я старался gcc-4.6.5
, gcc-4.8.1
, а также clang-3.3
, Что сбивает с толку то, что я явно не могу просить (bool)o
, так как Base
это частный база.
Это ожидаемое поведение?
Контроль доступа всегда идет последним. Цитата из стандарта:
10.2 Поиск имени члена [class.member.lookup]
1 Поиск имени члена определяет значение имени (id-выражение)
в рамках класса (3.3.7). Поиск имени может привести к неоднозначности, в
в этом случае программа является плохо сформированной. Для id-выражения, name
поиск начинается в области видимости этого; для квалифицированного идентификатора, имя
поиск начинается в области действия спецификатора nestedname. Поиск имени
происходит до контроля доступа (3.4, пункт 11).8 Если имя перегруженной функции найдено однозначно,
Разрешение перегрузки (13.3) также имеет место перед контролем доступа.
Неопределенности часто могут быть решены путем присвоения имени классу
название.
Причина, по которой рассматриваются оба оператора, заключается в том, что a) преобразование базового класса не скрыто производным (что было бы, если бы оба преобразовали в один и тот же тип), b) оба bool
а также int
может быть записано в стандартный вывод, c) ни одно из них не является лучшим соответствием, чем другое, поэтому разрешение перегрузки дает неоднозначность. Это приводит к серьезной ошибке еще до того, как контроль доступа вступит в игру.
Других решений пока нет …