Разрешение перегрузки функции с 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 добиться успеха в решении по этой перегрузке или нет.

Другие вопросы по тегам