Does compiler always use built-in type template params to decorate function name

92 Views Asked by At

When generating the function name, will the compiler always add template params into that name to make sure that the function name is unique? I am especially interested in the case where the template param is a built in type. Here is an example with some pseudocode:

template class<int32_t Size>
class Foo
{
public:
    ...

    // Signature does not depend on size
    void doSomething()
    {
        m_bar.doWork(Size);
    }
    
    // Some functions that depend on the value of Size
    ...

private:
    // Bar does not depend on Size
    Bar m_bar;

    // Some members that depend on the value of Size
    ...
};

Will instantiating the class above for two different values of Size result in two unique names for doSomething?

3

There are 3 best solutions below

10
Sneftel On BEST ANSWER

Possibly. Not necessarily.

The C++ standard does not mandate how implementations do their thing. While it has certain minor facilities that at least hint at the use of a thing called "name mangling", it certainly isn't necessary. You don't need a "linker", let alone a linker which works based on "symbol names", to make a standard-compliant C++ compiler.

What the C++ standard does mandate is that Foo<4>::doSomething() invokes Bar::doWork() with the argument 4, and that Foo<2>::doSomething() invokes Bar::doWork() with the argument 2. So it would not be okay for a compiler to confuse the two.

0
Yaroslav Fyodorov On

Yes. You must have two implementations of doSomething because they pass different params to doWork

This is how it looks with g++ on Mac with main that instantiates Foo with two different params:

#include <cstdint>

class Bar {
  public:
  int doWork(int32_t size) { return (int)size; } 
};

template <int32_t Size> class Foo 
{
  private:
  // Bar does not depend on Size
  Bar m_bar;

  public:

  // Signature does not depend on size
  void doSomething()
  {
    m_bar.doWork(Size);
  }
 };

int main(int argc, char* argv[]) {
    Foo<5>().doSomething();
    Foo<7>().doSomething();
    return 0;
}

Here part of the output of nm a.out which lists all the defined symbols - one function for Foo<5> and one for Foo<7>

...
0000000100003f14 T __ZN3FooILi5EE11doSomethingEv
0000000100003f3c T __ZN3FooILi7EE11doSomethingEv
...
0
Surt On

A possible alternative implementation to do this without name mangling would be to only make one function and store the template parameter in the virtual table.

Effectively making the compiler see something like this.

doSomething() {
  mBar.doWork(vtab.Size);
}

OK, I don't know any compiler that does this and as @TedLyngmo commented, his compiler inlined everything, which is definitely a good thing.