方法名称与 C++ 中的模板方法名称相同 [英] Method name same as template method name in C++
问题描述
令我惊讶的是,这个程序可以在 MSCV 和 GCC 中编译:
To my surprise this program compiles in both MSCV and GCC:
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;
}
显然,由于模板化方法的类型无法推导出,需要明确说明,所以情况并不模棱两可——仍然看起来有点阴暗——如果它是一个非模板化方法显然是不正确的.
Obviously, due to the fact that the type of the templated method cannot be deduced and needs to be explicitly stated, so the situation isn't ambigious - still it seems a bit shady - if it were a non-templated method that would be obviously incorrect.
我尝试使用谷歌搜索并查看标准的最后一个草案,但找不到答案 - 模板方法和普通方法的命名相同,仅在 C++ 中合法的返回类型有所不同,或者是编译器只是宽容?
I've tried googling and looking through the last draft of the standard, but couldn't find the answer - is same naming of a template method and a normal method that only differ by return type legal in C++, or are the compilers just being permissive?
推荐答案
这一直是合法的 C++.
This has always been legal C++.
14.5.6/2:
一个函数模板可以被其他函数模板和普通(非模板)函数重载.普通函数与函数模板无关(即,它永远不会被视为特化),即使它与潜在生成的函数模板特化具有相同的名称和类型.
A function template can be overloaded with other function templates and with normal (non-template) functions. A normal function is not related to a function template (i.e., it is never considered to be a specialization), even if it has the same name and type as a potentially generated function template specialization.
当使用像add
这样的template-id"语法时,只考虑具有足够模板参数的模板函数.所以 a.add
甚至不看非模板 add
是否匹配.
When using the "template-id" syntax like add<int>
, only template functions with enough template parameters are considered. So a.add<int>()
doesn't even look at whether the non-template add
matches.
当一个标识符同时命名一个普通函数和一个函数模板时,编译器将尝试推导函数模板的模板参数以获得模板函数特化.然后通过通常的函数重载逻辑比较所有普通函数和所有模板函数特化.[见 13.3.1/7.]
When an identifier names both a plain function and a function template, the compiler will try to deduce template arguments for the function template to get a template function specialization. Then all plain functions and all template function specializations are compared by the usual function overload logic. [See 13.3.1/7.]
在您的示例中,调用 a.add()
无法推导出模板版本的模板参数 T
.所以唯一可行的功能是非模板重载.
In your example, the call a.add()
can't deduce the template argument T
for the template version. So the only viable function is the non-template overload.
在类似情况下还有另一条规则:如果非模板函数和模板函数特化会产生歧义重载,则非模板函数获胜.[这条规则在 13.3.3 节中,在定义对于给定参数集使一个函数比另一个更好的定义的中间.]
There's also another rule that comes up in a similar situation: if a non-template function and a template function specialization would otherwise be an ambiguous overload, the non-template function wins. [This rule is in section 13.3.3, in the middle of the definition of what makes one function better than another for a given set of arguments.]
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;
}
这是有道理的,因为模板仍然可以被其他专业使用,或者通过显式使用<
尖括号>
.因此,使用非模板函数重载函数模板有点像添加显式特化,但麻烦更少.
This makes sense because the template can still be used by other specializations, or by explicitly using the <
angle brackets>
. So overloading a function template with a non-template function is sort of like adding an explicit specialization, but with fewer headaches.
这篇关于方法名称与 C++ 中的模板方法名称相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!