Тип оператора в частной базе
Я нашел кое-что странное поведение в C++: оператор приведения типов в закрытом базовом классе сбивает с толку компилятор при попытке разрешить неявное приведение:
#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
это частная база.
Это ожидаемое поведение?
1 ответ
Контроль доступа всегда идет последним. Цитата из стандарта:
10.2 Поиск имени члена [class.member.lookup]
1 Поиск имени члена определяет значение имени (id-выражения) в области видимости класса (3.3.7). Поиск имени может привести к неоднозначности, и в этом случае программа является плохо сформированной. Для id-выражения поиск имени начинается в области видимости этого класса; для квалифицированного идентификатора поиск имени начинается в области спецификатора nestedname. Поиск имени происходит перед контролем доступа (3.4, пункт 11).
8 Если имя перегруженной функции найдено однозначно, разрешение перегрузки (13.3) также имеет место перед контролем доступа. Неоднозначности часто могут быть решены путем присвоения имени его имени класса.
Причина, по которой рассматриваются оба оператора, заключается в том, что a) преобразование базового класса не скрыто производным (что было бы, если бы оба преобразовали в один и тот же тип), b) оба bool
а также int
может быть записано в стандартный вывод, c) ни одно из них не является лучшим соответствием, чем другое, поэтому разрешение перегрузки дает неоднозначность. Это приводит к серьезной ошибке еще до того, как контроль доступа вступит в игру.