Подтвердить что ты не робот

Скрытие шаблонов функций-членов. Какой компилятор прав?

Я написал следующий код, скрывающий шаблоны функций-членов.

#include <iostream>

struct A 
{
    template<int> void func()
    {
        std::cout<<"Function tamplate of A"<<std::endl;
    }
};

struct B : A 
{
    template<char> void func()
    {
        std::cout<<"Function tamplate of B"<<std::endl;
    }
    using A::func;
};

int main()
{
    B().func<0>();
}

Эта программа работает в компиляторе Clang. Live demo Clang

Но компилятор GCC дает ошибку двусмысленности. Live demo GCC

source_file.cpp: In function ‘int main()’:
source_file.cpp:22:17: error: call of overloaded ‘func()’ is ambiguous
     B().func<0>();

Итак, какой компилятор прав?

4b9b3361

Ответ 1

Что касается примера в OP: как было указано мной W.F., здесь важно, что это член шаблоны функций. Вы добавили декларацию using, которая указывает ([namespace.udecl]/15):

Когда декларация using приносит имена из базового класса в производную класс, функции-члены и шаблоны функций-членов в производный класс переопределяет и/или скрывает функции-члены и член функциональные шаблоны с тем же именем, список параметров-параметров, cv-qualification и ref-qualifier (если есть) в базе класс (а не конфликтующий).

Обратите внимание, что параметры шаблона не учитываются. И именно Кланг корректно обрабатывал код, скрывая версию int.


С другой стороны, если вы посмотрите пример tobi303, предложите под своим сообщением, GCC в порядке. Это просто не указано, чтобы как-то быть разрешено.

Во-первых, [temp.fct.spec]/3:

Трейлинг аргументов шаблона, которые можно вывести или полученные из шаблона-аргумента по умолчанию, могут быть опущены из списка явных шаблонных аргументов. [...] В контекстах, где вычет выполняются и не выполняются, или в ситуациях, когда вычет не производится, если список аргументов шаблона указан и он, наряду с любым значением по умолчанию аргументы шаблона, определяет шаблон одной функции специализации, то идентификатор шаблона является lvalue для функции специализированная специализация.

Текст, выделенный полужирным шрифтом, указывает, что ваша программа хорошо сформирована, только если аргумент шаблона, который мы даем, назначает одну специализацию. И, якобы, это не так, поскольку согласно [temp.arg.nontype]/1:

Аргумент шаблона для непигового шаблона-шаблона без шаблона должен быть одним из:

  • для нетипового шаблона-параметра интегрального или перечисляемого типа, преобразованное константное выражение типа Шаблон-параметры;

И 0 подходит для обеих перегрузок как преобразованное константное выражение. Из-за того, что для аргументов шаблона не было никакого рейтинга ICS, это неоднозначно.