2013-05-31 3 views
10

К моему удивлению, эта программа компилируется как в MSCV и GCC:имя метода совпадает с именем метода шаблона в C++

class A 
{ 
public: 
    int add() { return 0; } 
    template<typename T> 
    T add() { return T(); } 
}; 

int main() { 
    A a; 
    a.add(); 
    a.add<int>(); 
    return 0; 
} 

Очевидно, что из-за того, что тип шаблонного метода не может быть прослежена, и должен быть явно сформулированным, поэтому ситуация не является двусмысленной - все же она кажется немного теневой - если бы это был не шаблонный метод, который был бы явно неправильным.

Я пробовал поиск в Интернете и просматривал последний черновик стандарта, но не смог найти ответ - это то же самое название метода шаблона и обычный метод, который отличается только по типу возвращаемого типа в C++ или компиляторы просто разрешительны?

ответ

10

Это всегда было законным C++.

14.5.6/2:

Шаблон функции может быть перегружен с другими шаблонами функций и с нормальными (не шаблонными) функциями. Нормальная функция не связана с шаблоном функции (т. Е. Никогда не считается специализацией), даже если она имеет то же имя и тип, что и потенциально сгенерированная функция шаблона.

При использовании синтаксиса «шаблон-идентификатор», такого как add<int>, рассматриваются только функции шаблонов с достаточным количеством параметров шаблона. Итак, a.add<int>() даже не смотрит, соответствует ли не шаблон add.

Когда идентификатор называет как обычную функцию, так и шаблон функции, компилятор попытается вывести аргументы шаблона для шаблона функции, чтобы получить специализированную функцию шаблона. Затем все простые функции и все специализированные функции шаблонов сравниваются с обычной логикой перегрузки функции. [См. 13.3.1/7.]

В вашем примере вызов a.add() не может вывести аргумент шаблона T для версии шаблона. Таким образом, единственной жизнеспособной функцией является не-шаблонная перегрузка.

Существует также другое правило, которое возникает в аналогичной ситуации: если функция без шаблона и специализированная функция шаблона в противном случае были бы неоднозначной перегрузкой, выигрывает функция без шаблона. [Это правило в разделе 13.3.3, в середине определения того, что делает одну функцию лучше, чем другой для данного набора аргументов.]

class B 
{ 
public: 
    int f(int n) { return n+1; } 

    template<typename T> 
    T f(T n) { return n; } 
}; 

int main() { 
    B b; 
    b.f(1);  // both are viable, non-template wins 
    b.f<int>(1); // only the template is viable 
    return 0; 
} 

Это имеет смысл, так как шаблон по-прежнему может использоваться других специализаций или путем прямого использования угловых скобок <>. Поэтому перегрузка шаблона функции с помощью функции без шаблона похожа на добавление явной специализации, но с меньшим количеством головных болей.

+0

Woah, последнее еще интереснее - будет помнить об этом, спасибо! –

Смежные вопросы