[over.load] (original) (raw)
12 Overloading [over]
12.2 Overloadable declarations [over.load]
Not all function declarations can be overloaded.
Those that cannot be overloaded are specified here.
A program is ill-formed if it contains two such non-overloadable declarations in the same scope.
[ Note
:
This restriction applies to explicit declarations in a scope, and between such declarations and declarations made through ausing-declaration.
It does not apply to sets of functions fabricated as a result of name lookup (e.g., because ofusing-directives) or overload resolution (e.g., for operator functions).
— end note
]
Certain function declarations cannot be overloaded:
- Function declarations that differ only in the return type, the exception specification, or both cannot be overloaded.
- Member function declarations with the same name, the same parameter-type-list ([dcl.fct]), and the same trailing requires-clause (if any) cannot be overloaded if any of them is astaticmember function declaration ([class.static]).
Likewise, member function template declarations with the same name, the same parameter-type-list, the same trailing requires-clause (if any), and the same template-headcannot be overloaded if any of them is astaticmember function template declaration.
The types of the implicit object parameters constructed for the member functions for the purpose of overload resolution ([over.match.funcs]) are not considered when comparing parameter-type-lists for enforcement of this rule.
In contrast, if there is nostaticmember function declaration among a set of member function declarations with the same name, the same parameter-type-list, and the same trailing requires-clause (if any), then these member function declarations can be overloaded if they differ in the type of their implicit object parameter.
[ Example
:
The following illustrates this distinction:
class X {
static void f();
void f();
void f() const;
void f() const volatile;
void g();
void g() const;
void g() const volatile;
};
— end example
] - Member function declarations with the same name, the same parameter-type-list ([dcl.fct]), and the same trailing requires-clause (if any), as well as member function template declarations with the same name, the same parameter-type-list, the same trailing requires-clause (if any), and the same template-head, cannot be overloaded if any of them, but not all, have a ref-qualifier ([dcl.fct]).
[ Example
:
class Y {
void h() &;
void h() const &;
void h() &&;
void i() &;
void i() const;
};
— end example
]
[ Note
:
As specified in [dcl.fct], function declarations that have equivalent parameter declarations and requires-clauses, if any ([temp.constr.decl]), declare the same function and therefore cannot be overloaded:
- Parameter declarations that differ only in the use of equivalent typedef “types” are equivalent.
Atypedefis not a separate type, but only a synonym for another type.
[ Example
:
typedef int Int;
void f(int i);
void f(Int i);
void f(int i) { }
void f(Int i) { }
— end example
]
Enumerations, on the other hand, are distinct types and can be used to distinguish overloaded function declarations.
[ Example
:
enum E { a };
void f(int i) { }
void f(E i) { }
— end example
] - Parameter declarations that differ only in a pointer*versus an array[]are equivalent.
That is, the array declaration is adjusted to become a pointer declaration ([dcl.fct]).
Only the second and subsequent array dimensions are significant in parameter types ([dcl.array]).
[ Example
:
int f(char*);
int f(char[]);
int f(char[7]);
int f(char[9]);
int g(char()[10]);
int g(char[5][10]);
int g(char[7][10]);
int g(char()[20]);
— end example
] - Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent.
That is, the function type is adjusted to become a pointer to function type ([dcl.fct]).
[ Example
:
void h(int());
void h(int (*)());
void h(int x()) { }
void h(int (*x)()) { }
— end example
] - Parameter declarations that differ only in the presence or absence ofconstand/orvolatileare equivalent.
That is, theconstandvolatiletype-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called.
[ Example
:
typedef const int cInt;
int f (int);
int f (const int);
int f (int) { }
int f (cInt) { }
— end example
]
Only theconstandvolatiletype-specifiers at the outermost level of the parameter type specification are ignored in this fashion;constandvolatiletype-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.116
In particular, for any typeT, “pointer toT”, “pointer toconst T”, and “pointer tovolatile T” are considered distinct parameter types, as are “reference toT”, “reference toconst T”, and “reference tovolatile T”. - Two parameter declarations that differ only in their default arguments are equivalent.
[ Example
:
Consider the following:
void f (int i, int j);
void f (int i, int j = 99);
void f (int i = 88, int j);
void f ();
void prog () {
f (1, 2);
f (1);
f ();
}
— end example
]
— end note
]