it-swarm.com.ru

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

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

65
yesraaj

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

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

Вступление

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

  • Объявления
  • Юридические лица

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

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

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

В этом определении отсутствует возвращаемый тип, который является частью сигнатуры специализации шаблона функции (т. Е. Объявления функции, которая объявляет функцию, которая является специализация шаблона), как указал 14.5.5.1 (в последних рабочих документах C++ 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

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

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

81
Johannes Schaub - litb

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

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

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

  1. безусловное имя функции
  2. Область имен или этого имени, и если имя имеет внутренняя связь, единица перевода, в которой объявлено имя
  3. Квалификация функции const, volatile или const volatile
  4. типы параметров функции
  5. тип возврата , если функция генерируется из шаблона функции
  6. параметры шаблона и аргументы шаблона , если функция генерируется из шаблон функции

Как указано 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'); 
10
Nicola Bonelli

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

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)
}
2
Eclipse