Является ли возвращаемый тип частью сигнатуры функции?
в C++ тип возвращаемого значения считается частью сигнатуры функции? и никакая перегрузка не допускается только с измененным типом возврата.
3 ответа:
обычные функции не включают тип возвращаемого значения в свою подпись.
(Примечание: я переписал этот ответ, и комментарии ниже не относятся к этой ревизии - см. историю редактирования для получения подробной информации).
введение
однако вопрос о функциях и объявлениях функций в стандарте является сложным. Есть два слоя, которые должны быть считается:
- декларации
- объекты
так называемые объявление функции может объявлять объект функции или объект шаблона. Если объявлена сущность функции, то вы либо должны иметь дело с явной специализацией шаблона функции (со всеми указанными аргументами), либо с объявлением обычной функции. Если объявлена сущность шаблона, то вы объявляете основной шаблон функции или явная специализация, где некоторые аргументы не указаны. (Это очень похоже на отношение "объявления объекта" и объектов или ссылок: первый может объявить либо объект, либо ссылку. Так что объект декларация не обязательно объявлять объект!).
стандарт определяет сигнатуру функции, чтобы включить следующую
1.3.10
:типы его параметров и, если функция является членом класса, CV-квалификаторы (если таковые имеются) для самой функции и класса, в котором объявлена функция-член. Сигнатура специализации шаблона функции включает типы его аргументов шаблона. (14.5.5.1)
в этом определении отсутствует возвращаемый тип, который и часть сигнатуры специализации шаблона функции (т. е. объявление функции, которое объявляет функцию, которая является специализацией шаблона), как указано
14.5.5.1
(последние рабочие документы C++0x исправили это, чтобы уже упомянуть тип возврата в1.3.10
тоже):сигнатура специализации шаблона функции состоит из сигнатуры шаблона функции и фактических аргументов шаблона (явно заданных или выведенных).
сигнатура шаблона функции состоит из сигнатуры функции, возвращаемого типа и списка параметров шаблона.
Ну и что точно ли подпись содержит, опять же?
Итак, когда мы спрашиваем о подписи a функции, мы должны дать два ответа:
- для функций, которые являются специализациями шаблонов функций, сигнатура включает тип возвращаемого значения.
- для функций, которые не являются специализациями, возвращаемый тип не является частью подписи.
обратите внимание, однако, что возвращаемый тип, в любом случае, и значительная часть типа функции. То есть недопустимо следующее:
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-квалификатор (если таковые имеются) на самой функции или шаблоне функции. Подпись шаблона функции дополнительно включает его возвращаемый тип и его список параметров шаблона. Сигнатура специализации шаблона функции включает в себя сигнатуру шаблона, для которого он является специализацией, и его аргументы шаблона (явно заданные или выведенные). [Примечание: подписи используются в качестве основы для искажения имен и связывания. - конец Примечание ]
это зависит, если функция является шаблон функции или нет.
на шаблоны C++ -- полные руководства, Jusuttis дает другое определение, данное в стандарте C++, но с эквивалентными последствиями:
мы определяем сигнатуру функции как следующую информацию:
- The имя функции
- The класс или пространство имен область действия этого имени, и если имя имеет внутреннюю связь, единица перевода, в которой объявлено имя
- The
const
,volatile
илиconst volatile
квалификация функции- The типы параметров функции
- возвращение тип, если функция генерируется из шаблона функция
- The параметры шаблона и шаблон аргументы, если функция генерируется из шаблона функция
как 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');
они достаточно часть типа, что вы можете перегружать функции на основе типов указателей функций, которые отличаются только типом возврата:
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) }