Адрес перегруженной функции
Помимо выражений вызова функций, где происходит разрешение перегрузки, имя перегруженной функции может появляться в следующих 7 контекстах:
| # | Контекст | Целевой объект |
|---|---|---|
| 1 | инициализатор в объявлении объекта или ссылки | инициализируемый объект или ссылка |
| 2 | в правой части выражения присваивания | левая часть присваивания |
| 3 | в качестве аргумента вызова функции | параметр функции |
| 4 | в качестве аргумента пользовательского оператора | параметр оператора |
| 5 | в операторе return |
тип возвращаемого значения функции |
| 6 |
явное приведение типа или static_cast аргумент |
целевой тип приведения |
| 7 | нетиповой шаблонный аргумент | тип шаблонного параметра |
В каждом контексте имя перегруженной функции может быть предваряемо оператором обращения к адресу &, и может быть заключено в избыточные скобки.
Во всех этих контекстах, функция, выбранная из набора перегрузок, — это функция, тип которой соответствует типу указателя на функцию, ссылке на функцию или указателю на член-функцию, ожидаемому целевым объектом.
Типы параметров и тип возвращаемого значения функции должны точно соответствовать целевому объекту. Неявные преобразования не учитываются (например, функция, возвращающая указатель на производный класс, не будет выбрана при инициализации указателя на функцию, возвращающую указатель на базовый класс).
Если имя функции относится к шаблону функции, то сначала выполняется вывод аргументов шаблона, и если это успешно, то генерируется единственная специализация шаблона, которая добавляется в набор перегрузок для рассмотрения. Все функции, чьи связанные ограничения не удовлетворяются, исключаются из набора.(с C++20) Если более одной функции из набора соответствует целевому объекту, и хотя бы одна функция не является шаблоном, специализации шаблонов исключаются из рассмотрения. Для любой пары нешаблонных функций, где одна более ограничена, чем другая, менее ограниченная функция исключается из набора.(с C++20) Если все оставшиеся кандидаты являются специализациями шаблонов, менее специализированные удаляются, если есть более специализированные. Если после удалений остается более одного кандидата, программа некорректна.
Пример
int f(int) { return 1; }
int f(double) { return 2; }
void g(int(&f1)(int), int(*f2)(double)) { f1(0); f2(0.0); }
template<int(*F)(int)>
struct Templ {};
struct Foo
{
int mf(int) { return 3; }
int mf(double) { return 4; }
};
struct Emp
{
void operator<<(int (*)(double)) {}
};
int main()
{
// 1. initialization
int (*pf)(double) = f; // selects int f(double)
int (&rf)(int) = f; // selects int f(int)
int (Foo::*mpf)(int) = &Foo::mf; // selects int mf(int)
// 2. assignment
pf = nullptr;
pf = &f; // selects int f(double)
// 3. function argument
g(f, f); // selects int f(int) for the 1st argument
// and int f(double) for the second
// 4. user-defined operator
Emp{} << f; //selects int f(double)
// 5. return value
auto foo = []() -> int (*)(int)
{
return f; // selects int f(int)
};
// 6. cast
auto p = static_cast<int(*)(int)>(f); // selects int f(int)
// 7. template argument
Templ<f> t; // selects int f(int)
// prevent "unused variable" warnings as-if by [[maybe_unused]]
[](...){}(pf, rf, mpf, foo, p, t);
}Ссылки
- Стандарт C++23 (ISO/IEC 14882:2023):
- 12.3 Адрес перегруженной функции [over.over]
- Стандарт C++20 (ISO/IEC 14882:2020):
- 12.5 Адрес перегруженной функции [over.over]
- Стандарт C++17 (ISO/IEC 14882:2017):
- 16.4 Адрес перегруженной функции [over.over]
- Стандарт C++14 (ISO/IEC 14882:2014):
- 13.4 Адрес перегруженной функции [over.over]
- Стандарт C++11 (ISO/IEC 14882:2011):
- 13.4 Адрес перегруженной функции [over.over]
- Стандарт C++98 (ISO/IEC 14882:1998):
- 13.4 Адрес перегруженной функции [over.over]
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/overloaded_address