Search code examples
c++templatesc++11name-mangling

C++ template-argument dependent decltype in ABI mangled name


Consider the following function:

template <typename A, typename B>
auto Min(A&& a, B&& b)
        -> decltype(a < b ? std::forward<A>(a) : std::forward<B>(b))
{
    return a < b ? std::forward<A>(a) : std::forward<B>(b);
}

The fragment Min(0, 1) causes the template to be instantiated as Min<int, int>. Strangely, the mangled name for Min with g++ and clang for my code is _Z3MinIiiEDTqultfp_fp0_cl7forwardIT_Efp_Ecl7forwardIT0_Efp0_EEOS0_OS1_ (aka: decltype (({parm#1}<{parm#2})?((forward<int>)({parm#1})) : ((forward<int>)({parm#2}))) Min<int, int>(int&&, int&&)). In other words, the expression used to deduce the return type is part of the mangled name. Personally, I expected something slightly more sane along the lines of: _Z3MinIiiET_OS0_OT0_ (aka: int Min<int, int>(int&&, int&&)). Why is this not the case?


It seems that g++ only puts the decltype expression in cases where it is actually needed, as these forms are both _Z3Maxii:

  • auto Max(int x, int y) -> int
  • auto Max(int x, int y) -> decltype(0)

Solution

  • If you overload function templates, the functions produced by these function templates (called a function template specialization) need to be different. Hence the C++ Standard specifies that the signature of function template specializations include the signature of the function template from which the specialization was generated.

    Otherwise if both templates would instantiate functions that have the same function type, they would clash.