Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-const pointer prefers const T& overload to const T*

Suppose I have two overloads of a function

template <typename T>
void f(const T&) {
    cout << "f(T&)" << endl;
}

template <typename T>
void f(const T*) {
    cout << "f(T*)" << endl;
}

Why does f(new int) resolves to the f(const T&) instead of f(const T*)? Anywhere in the standard talks about this counter-intuitive behavior?

http://ideone.com/kl8NxL

like image 733
Kan Li Avatar asked Feb 16 '17 01:02

Kan Li


People also ask

What is a non constant pointer?

A pointer to a non-const value can change the value it is pointing to. These can not point to a const value. A pointer to a const value treats the value as const when accessed through the pointer, and thus can not change the value it is pointing to.

Can you pass a non-const to a const?

For instance, you can pass non-const variables to a function that takes a const argument. The const-ness of the argument just means the function promises not to change it, whether or not you require that promise.

Can a const reference be bound to a non-const object?

No. A reference is simply an alias for an existing object. const is enforced by the compiler; it simply checks that you don't attempt to modify the object through the reference r .

Can const methods be used by non-const objects?

const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.


1 Answers

For overload resolution with template deduction, the first step is to resolve the templates. Then non-template ordering is applied to the results. In your code the template resolutions are:

void f(int * const &)   // 1

void f(int const *)     // 2

According to C++14 [over.ics.ref], a reference binding directly to an argument as in (1) is an identity conversion (even if there are added cv-qualifiers). The binding of T to T const & is a direct binding, i.e. no temporaries are created and bound.

However, (2) involves a qualification conversion. The argument type int * must be converted to const int * before it matches the function parameter.

The identity conversion is considered a sub-sequence of any non-identity conversion sequence, so (1) wins according to the sub-sequence rule [over.ics.rank]/3.1.1

like image 101
M.M Avatar answered Oct 09 '22 02:10

M.M