Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload function for both arrays-of-const and pointers-to-const

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?

like image 556
Fabian Knorr Avatar asked Oct 06 '15 07:10

Fabian Knorr


People also ask

Can const functions be overloaded?

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.

Can we overload const functions in C++?

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.

What is an overloaded function in C++?

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.

Which of the given member functions can be overloaded?

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.


Video Answer


1 Answers

Why it doesn't work

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.

Solution

Pass the pointer by reference in the second overload:

void foo(const int *&) {
    std::cout << "foo(const int *)\n";
}

LIVE DEMO

Why the suggested solution works

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].

like image 110
101010 Avatar answered Nov 15 '22 20:11

101010