ABI错位名称中依赖于C++模板参数的decltype

Tra*_*kel 14 c++ templates name-mangling c++11

考虑以下功能:

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);
}
Run Code Online (Sandbox Code Playgroud)

该片段Min(0, 1)使模板被实例化为Min<int, int>.奇怪的是,Min我的代码使用g ++和clang的错误名称是_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&&).换句话说,用于推断返回类型的表达式是受损名称的一部分.就我个人而言,我期望的东西会更加清晰:( _Z3MinIiiET_OS0_OT0_又名:) int Min<int, int>(int&&, int&&).为什么不是这样?


似乎g ++只将decltype表达式放在实际需要它的情况下,因为这些形式都是_Z3Maxii:

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

ken*_*ytm 5

gcc使用“ Italium C ++ ABI”进行改写,它指定

如果的操作数表达式与实例decltype无关,则直接对结果类型进行编码。例如:

      int x;
      template<class T> auto f(T p)->decltype(x);
        // The return type in the mangling of the template signature
        // is encoded as "i".
      template<class T> auto f(T p)->decltype(p);
        // The return type in the mangling of the template signature
        // is encoded as "Dtfp_E".
      void g(int);
      template<class T> auto f(T p)->decltype(g(p));
        // The return type in the mangling of the template signature
        // is encoded as "DTcl1gfp_E".
Run Code Online (Sandbox Code Playgroud)

第三个示例是OP的简化版本,它也直接编码整个表达式,因为它与实例相关。依赖实例化的定义为

如果表达式是类型依赖的或值依赖的,或者它的子表达式是类型依赖的或值依赖的,则表达式是实例化的。例如,如果p是类型相关的标识符,则表达式sizeof(sizeof(p))既不依赖类型也不依赖于值,而是依赖于实例化(如果替换模板参数后p发现不完整,则表达式可能无效。类型)。类似地,如果源形式包含依赖实例的表达式,则用源代码表示的类型是依赖实例的。例如,类型表单double[sizeof(sizeof(p))](具有与p类型相关的标识符)是实例化相关的

关键是依赖于实例化的表达式“在替换后可能会变得无效”,这很可能是因为它们在处理过程中以未求值形式保留的原因。


Joh*_*itb 4

如果重载函数模板,则这些函数模板(称为函数模板特化)生成的函数需要不同。因此,C++ 标准指定函数模板特化的签名包括生成特化的函数模板的签名。

否则,如果两个模板都实例化具有相同函数类型的函数,它们就会发生冲突。