简体   繁体   中英

template deduction: const reference and const pointer

template <typename T>
void f(T t)
{}

int x = 1;
const int & rx = x;
const int * px = &x;
f(rx); // t is int
f(px); // t is const int *, instead of int *, WHY???

I'm confused now. According to Effective Modern c++ ,

It's important to recognize that const is ignored only for by-value parameters. As we've seen, for parameters that are references-to- or pointers-to-const, the constness of expr is preserved during type deduction.

I think it means

template <typename T>
void f(T * t)
{}
f(px); // t is const int *

template <typename T>
void f(T & t)
{}
f(cx); // t is const int &

template <typename T>
void f(T t)
{}
f(value); // const or volatile of value will be ignored when the type of the parameter t is deduced

So I think when f(px) above, t should be int * , but in fact it is const int * .

Why the const of reference is ignored but the const of pointer isn't? Or, why isn't rx const int & ?

Only top-level const/volatile qualifiers are ignored. All others are inherent qualities of your type. In other words, you're copying a pointer - it means the function operates on a copy and any modifications to it (like assigning another variable's address) do not modify the original pointer. But if you pass a pointer to const int , having the function modify the integer is very much counter-intuitive.

template <typename T>
void f(T t)
{
    t = &another_variable; // ok
}

f(px);

and

void f(T t)
{
    *t = 42; // not ok!
}

f(px); // secretly modifying `x` through a pointer to const...

Reference: this answer for pointer to const vs. const pointer differences

So I think when f(px) above, px should be int *, but in fact it is const int *.

The point is the type of parameter, behaviors change for passed-by-value and passed-by-reference/pointer .

When passed-by-value, the constness of the argument itself is ignored. For a pointer parameter, the constness of pointer is ignored (const pointer -> pointer), but the constness of pointee is still preserved (pointer to const -> pointer to const).

It does make sense because when pass a pointer, the pointer itself is copied, but the pointee is the same, they're both pointing to the same thing, so constness of pointee is preserved; from the point of callers, they won't want the object to be modified, they might use it later. While pass a reference (reference doesn't matter in fact here), you'll get a brand new value copied, which has nothing to do with the original one, then constness is ignored.

As the following explanations in the book, when const pointer to const (a const char* const ) passed,

template<typename T>
void f(T param); // param is still passed by value

const char* const ptr = // ptr is const pointer to const object
  "Fun with pointers";

f(ptr); // pass arg of type const char * const

The type deduced for param will be const char* .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM