Разрешение перегрузки функции с nullptr в качестве аргумента
Рассмотрим код ниже. Хотя обе перегрузки fun
принимать указатели, проходя мимо nullptr
в fun
не приводит к ошибке компиляции. Принимая во внимание, что очень похожая функция bun
не может скомпилировать. Когда я печатаю типы аргумента i
с помощью typeid(i).name()
(после изменения кода просто для печати) я получаю тот же тип, просто int*
, Какое правило разрешает неоднозначность в fun
случай, но не для bun
? Заранее спасибо!
#include <iostream>
struct Foo {
int sth;
};
template< class U>
void fun(decltype(U::sth)* i){
std::cout << "1" << std::endl;
}
template< class U>
void fun(U* i){
std::cout << "2" << std::endl;
}
void bun(decltype(Foo::sth)* i){
std::cout << "3" << std::endl;
}
void bun(Foo* i){
std::cout << "4" << std::endl;
}
int main ( )
{
fun<Foo>(nullptr);
// bun(nullptr); --> call of overloaded 'bun(std::nullptr_t)' is ambiguous
return 0;
}
-----------------------
output : 1
1 ответ
Ну, на самом деле, GCC принимает ваш код, а Clang - нет. Так что поначалу не очевидно, является ли вызов неоднозначным.
Вы спрашиваете, какое правило разрешает неоднозначность в fun
дело; GCC, очевидно, считает, что такое правило существует. Я представляю себе правило, которое применяет GCC, это правило [over.match.best]/1.7, которое предпочитает более специализированный шаблон функции, чем менее специализированный.
Процедура определения того, какой шаблон функции является более специализированным, чем другой, описана в [temp.func.order] и подробно объясняется в этом ответе SO. Тем не менее, вы заметите, что при попытке применить эту процедуру к двум перегрузкам fun
как в этом вопросе, мы сталкиваемся с проблемой, что уникальный синтезированный тип, который должен быть заменен U
при первой перегрузке потребуется член с именем sth
и характер этого члена не уточняется, и хотя человеку может быть ясно, что вычет во втором fun
перегрузка должна преуспеть независимо от того, что sth
Тип, компилятор может быть не в состоянии доказать это.
Это CWG 1157. Поскольку этот вопрос все еще остается открытым без предложенного решения, у меня нет понимания, намеревается ли WG21 добиться успеха в решении по этой перегрузке или нет.