Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method name same as template method name in C++

Tags:

c++

templates

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.

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?

like image 802
Kornel Kisielewicz Avatar asked May 31 '13 20:05

Kornel Kisielewicz


1 Answers

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.

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.

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.]

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.

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.

like image 51
aschepler Avatar answered Sep 22 '22 13:09

aschepler