Определенное пользователем неявное преобразование из класса enum при вызове перегруженного оператора не
Рассмотрим следующий пример:
struct ConvertibleStruct {};
enum class ConvertibleEC {};
struct Target {
// Implicit conversion constructors
Target(ConvertibleStruct) {}
Target(ConvertibleEC) {}
};
Target operator~(const Target& t) {
return t;
}
Target anotherFunction(const Target& t) {
return t;
}
int main() {
ConvertibleStruct t;
ConvertibleEC ec;
~t; // 1. Works finding the operator overloaded above
~ec; // 2. Fails to compile on clang 3.4 and gcc 4.8.2
operator~(ec); // 3. Works finding the operator overloaded above
anotherFunction(ec); // 4. Works
}
Версии компилятора:
Приведенные выше выводы относятся к clang 3.4
и gcc 4.8.2
. Тест 2. на самом деле прекрасно компилируется на gcc 4.7.3
с -std=c++11
. Возможно, ошибка в ранней реализации GCC C++11?
Утверждения:
- учитывая, что 1. компиляции, определяемые пользователем неявные преобразования проверяются при вызове оператора
~
. - учитывая, что 4. компиляции, определяемые пользователем неявные преобразования проверяются на
enum class
объекты.
Вопросы:
- являются вышеуказанные утверждения правильные?
- если они есть, то почему 2. не удается скомпилировать?
- учитывая, что 2. не удается скомпилировать, почему 3. компилировать?
1 ответ:
Второй тест,
~ec
, наталкивается на особенность поиска имен операторов в выражениях: [over.спичка.опер] / 3 (из "древнего" N3797):Для унарного оператора
@
с операндом типа, cv-безусловная версия которогоT1
[...]Набор кандидатов, не являющихся членами Совета, является результатом неквалифицированного отбора. поиск
operator@
в контексте выражения в соответствии с обычные правила поиска имен в неквалифицированных вызовах функций разве что все функции-члены игнорируются. однако, если операнд отсутствует имеет тип класса, только те функции, не являющиеся членами в наборе подстановок которые имеют первый параметр типаT1
или " ссылка на (возможно cv-квалифицированный)T1
", КогдаT1
является типом перечисления [...] являются функции-кандидаты .Таким образом,
::operator~(const Target&)
не должно быть найдено/использовано с A для выражения с унарным оператором, примененным к операнду типаConvertibleEC
.
Для первого,
И в третьем, и в четвертом тесте используется не поиск оператора, а обычный неквалифицированный поиск. Обычный неквалифицированный поиск находит~t
, операнд относится к типу класса, и указанное выше исключение не применяется.::operator~(const Target&)
(в случаях 1 и 3) иanotherFunction
(в случае 4).