Подтвердить что ты не робот

Является ли часть возвращаемого типа сигнатурой функции?

В С++, является ли возвращаемый тип рассмотренной частью сигнатуры функции? и перегрузка не допускается с изменением типа возвращаемого типа.

4b9b3361

Ответ 1

Нормальные функции не включают тип возврата в свою подпись.

(примечание: я переписал этот ответ, а приведенные ниже комментарии не относятся к этой ревизии - подробности см. в истории изменений).

Введение

Однако вопрос о функциях и объявлениях функций в Стандарте сложный. Необходимо учитывать два слоя:

  • Объявления
  • Сущности

Объявление так называемой функции может объявлять объект функции или объект шаблона. Если объявляется объект функции, то вы либо должны иметь дело с явной специализацией шаблона функции (со всеми указанными аргументами), либо с объявлением обычной функции. Если объект шаблона объявлен, тогда вы объявляете шаблон первичной функции или явную специализацию, в которой некоторые аргументы не указаны. (Это очень похоже на отношение "объявления объекта" и объектов или ссылок: первый может объявить либо объект, либо ссылку. Таким образом, объявление объекта может не обязательно объявлять объект!).

Стандарт определяет подпись функции, которая включает следующее в 1.3.10:

Типы его параметров и, если функция является членом класса, cv-квалификаторы (если есть) для самой функции и класса, в котором объявлена ​​функция-член. Подпись специализации шаблона включает в себя типы аргументов шаблона. (14.5.5.1)

В этом определении отсутствует тип возвращаемого значения, который является частью сигнатуры специализированной функции (т.е. объявление функции, объявляющей функцию, которая является специализацией шаблона), как указано 14.5.5.1 (недавнее С++ 0x рабочие документы исправлены, что уже упоминать тип возврата в 1.3.10 тоже):

Подпись специализированной функции шаблона состоит из сигнатуры шаблона функции и фактических аргументов шаблона (явно или неявно).

Подпись шаблона функции состоит из его сигнатуры функции, ее типа возврата и списка параметров шаблона.

Итак, что именно содержит подпись, снова?

Итак, когда мы спрашиваем о сигнатуре функции, мы должны дать два ответа:

  • Для функций, которые являются специализациями шаблонов функций, подпись включает тип возврата.
  • Для функций, не являющихся специализациями, возвращаемый тип не является частью подписи.

Обратите внимание, однако, что тип возврата в любом случае является значительной частью типа функции. То есть следующее недопустимо:

void f();
int (*pf)() = &f; // different types!

Когда недогрузка недопустима, если отличается только тип возврата?

В настоящее время основные компиляторы отклоняют следующий код:

int f();
double f(); // invalid

Но примите следующий код:

template<typename T> int f();
template<typename T> double f(); // invalid?

Однако Стандарт запрещает объявление функции, которое отличается только от типа возврата (при определении, когда перегрузка является допустимой, а когда нет). Он не определяет точно, что означает "отличается только обратным типом".


Стандартные ссылки на параграфы:

  • Когда может быть перегружено объявление функции: 13.1
  • Что такое объявление функции: 7/2 и 7/5
  • Что такое подпись шаблона/специализации функции: 14.5.5.1

Для справки, вот что показывает последний проект С++ 0x n3000 о "сигнатуре" в 1.3.11, который гораздо более полно в своем охвате различных типов объектов:

имя и список типов параметров (8.3.5) функции, а также класс или пространство имен, членом которого он является. Если шаблон функции или функции является членом класса, его подпись дополнительно включает в себя cv-qualiers (если есть) и ref-quali fi (если есть) в самой функции или в шаблоне функции. Подпись шаблона функции дополнительно включает его тип возвращаемого значения и список параметров шаблона. Подпись специализированной функции шаблона включает в себя подпись шаблона, для которой она является специализацией и ее аргументами шаблона (явно или специфицировано). [Примечание. Подписи используются в качестве основы для манипулирования именами и связывания. - конечная нота]

Ответ 2

Это зависит от того, является ли функция шаблоном функции или нет.

В С++ Templates - полные руководства, Jusuttis предоставляет другое определение, данное в стандарте С++, но с эквивалентными последствиями:

Мы определяем сигнатуру функции как следующую информацию:

  • Неквалифицированное имя функции
  • Класс или пространство имен этого имени, и если имя имеет внутреннюю связь, единица перевода, в которой объявлено имя
  • Квалификация const, volatile или const volatile функции
  • Типы параметров функции
  • его тип возврата, если функция создается из шаблона функции
  • Параметры шаблона и аргументы шаблона, если функция генерируется из шаблона функции

Как предлагалось litb, стоит выяснить, почему тип возврата является частью сигнатуры функции шаблона.

Функции могут сосуществовать в программе, если они имеют различные подписи.

. Тем не менее, если тип возврата является параметром шаблона:

template <typename T>
T foo(int a)
{return T();}

возможно создать две функции, которые отличаются только возвращаемым типом:

foo<int>(0);
foo<char>(0);

Не только: как правильно сказано litb, также возможно перегрузить две функции шаблона, которые отличаются только типом возврата, даже если тип возвращаемого значения не является зависимым именем. Вот его пример:

template<class T> int foo(T)
{}

template<class T> bool foo(T)
{}

// at the instantiation point it is necessary to specify the cast
// in order not to face ambiguous overload

((int(*)(char))foo<char>)('a'); 

Ответ 3

Они достаточно часть того типа, который вы можете перегрузить функции на основе типов указателей функций, которые отличаются только возвращаемым типом:

int IntFunc() { return 0; }
char CharFunc() { return 0; }

void FuncFunc(int(*func)()) { cout << "int\n"; }
void FuncFunc(char(*func)()) { cout << "char\n"; }


int main()
{
    FuncFunc(&IntFunc); // calls void FuncFunc(int_func func)
    FuncFunc(&CharFunc); // calls void FuncFunc(char_func func)
}