I can capture an array along with its (compile-time) size using a template function like so:
template<int N>
void foo(const int (&)[N]) {
std::cout << "foo(const int (&)[N])\n";
}
However, I'd like to overload foo
to also allow pointers-to-const, so that the first overload is used when the function is called on an array type, and the second one when it's called on a pointer directly.
void foo(const int *) {
std::cout << "foo(const int *)\n";
}
int main() {
int a[1] = { 0 };
foo(a);
const int b[1] = { 0 };
foo(b);
}
Try it on ideone
Here, the first overload is called for a
, the second one for b
.
My guess is that for a
, the compiler must perform a conversion-to-const which means that foo(const int *)
is not a perfect match, but I'm lost to why this is not even an ambigous function call.
How can I change the code so that the first overload is called in both cases?
Function overloading and const keyword in C++In C++, we can overload functions. Some functions are normal functions; some are constant type functions. Let us see one program and its output to get the idea about the constant functions and normal functions.
C++ allows functions to be overloaded on the basis of the const-ness of parameters only if the const parameter is a reference or a pointer.
C++ lets you specify more than one function of the same name in the same scope. These functions are called overloaded functions, or overloads. Overloaded functions enable you to supply different semantics for a function, depending on the types and number of its arguments.
Key Points Both functions and operators can be overloaded. C++ allows you to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading respectively.
In your example both overloads are considered by the compiler matches. Here comes overload resolution to the rescue to eliminate one and keep the best match. According to the draft standard N4527 13.3.3/1.6 Best viable function [over.match.best]:
F1 is not a function template specialization and F2 is a function template specialization
In our case F1 is void foo(const int *)
and F2
is template<int N>
void foo(const int (&)[N])
. Thus, F1 will be prefered over F2 because F1 is not a template specialization while F2 is.
Pass the pointer by reference in the second overload:
void foo(const int *&) {
std::cout << "foo(const int *)\n";
}
LIVE DEMO
Now as dyp already mentioned in the comments, if you pass the pointer by reference as shown earlier above, this match is broken because const int *&
cannot match to int*
neither to int[N]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With