2016-05-18 - C++ and function signatures

C++ is complex. i constantly get surprised by corner cases. few days back Sławek asked me if i know, if return type of a function is a part of a function's signature. i said “no” and he replied “well – i though so too”. it runs out that the correct answer is… “it depends”. let's have a look at some examples:

int f1(int);
 
template<typename T>
int f2(int);
 
template<typename T>
struct A
{
  template<typename U>
  int f3(int);
};
 
template<typename T>
struct B
{
  int f4(int);
};
 
void foo()
{
  f1(1);
  f2<double>(2);
 
  A<double> a;
  a.f3<double>(3);
 
  B<double> b;
  b.f4(4);
}

now let's see what's the compiler's output:

clang++ -Wall -std=c++14 syms.cpp -c
nm syms.o | c++filt  | grep U

and we get:

   U f1(int)
   U int f2<double>(int)
   U int A<double>::f3<double>(int)
   U B<double>::f4(int)

note that f2 and f3 do have return types in their signatures, while f1 and f4 don't!

as usually – that's the corner case in the C++ spec. looking at C++14 spec 1.3.17 through 1.3.22, explains the secret:

long story short – if you have a template (member) function (partial) (specialization), return type is a part of the signature. otherwise its not.