Рассмотрим следующую функцию:
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);
}
Фрагмент Min(0, 1)
вызывает создание шаблона как Min<int, int>
, Странно, покалеченное имя для Min
с g ++ и clang для моего кода _Z3MinIiiEDTqultfp_fp0_cl7forwardIT_Efp_Ecl7forwardIT0_Efp0_EEOS0_OS1_
(Ака: 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)
Если вы перегружаете шаблоны функций, функции, создаваемые этими шаблонами функций (так называемая специализация шаблонов функций), должны отличаться. Следовательно, Стандарт C ++ указывает, что сигнатура специализаций шаблона функции включает в себя сигнатуру шаблона функции, из которой была создана специализация.
В противном случае, если оба шаблона будут создавать функции с одинаковым типом функции, они будут конфликтовать.
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".
Третий пример — сокращенная версия OP, которые также кодируют все выражение напрямую, потому что оно зависит от экземпляра. Конкретизация-зависимый определяется как:
Выражение Инстанциация-зависимой если он зависит от типа или значения, или имеет подвыражение, которое зависит от типа или значения. Например, если
p
типозависимый идентификатор, выражениеsizeof(sizeof(p))
не зависит ни от типа, ни от значения, но зависит от экземпляра (и может оказаться недействительным, если после подстановки аргументов шаблонаp
оказывается неполного типа). Точно так же тип, выраженный в исходном коде, зависит от экземпляра, если исходная форма включает Инстанциация-зависимой выражение. Например, тип формыdouble[sizeof(sizeof(p))]
(сp
зависимый от типа идентификатор) Инстанциация-зависимой.
Ключевым моментом является то, что зависящие от экземпляра выражения «могут оказаться недействительными после подстановки», что, вероятно, является причиной того, что они остаются в неоцененной форме в календаре.