Simon Sirak
Simon Sirak

Reputation: 195

How can const be applied to template argument types outside of the parameter list in C++?

I am studying C++ templates, and I got stuck thinking about the interaction between const and types that are arguments to template functions. Specifically, I am thinking about how consts interact with template types when applied outside of the template parameter list.

I have tried looking for this interaction in C++ Primer 5th ed (Lippman) and in the C++11 standard draft, but const in this context is either not explicitly mentioned or (in the case of the standard) rather complex in its description (I'm still somewhat new to C++).

Here is a code example of my problem:

template<typename T>
const T & constify(T & t) {
    return t;
}

...

int* i = 0x12345678; 
constify(i);

I have two different expectations of the return type:

  1. The deduced return type is const (int *) &, i.e the const is applied afterwards, so that we cannot modify the int pointer but we can modify what it points to.
  2. The deduced return type is const int * &, i.e all declarators and qualifiers are applied all at once instead of as in 1. Here, we can no longer modify the int pointed to by the integer, but we can modify the pointer itself.

For me, the first one makes more sense because it has a natural "substitution-like" rule behind it, similar to typedef. But my question is; which of these (if any) is correct and why?

Upvotes: 6

Views: 1842

Answers (3)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136208

const consistent location is on the right of the type. Some declarations, like variables, also allow putting const on the left, but others, like member function definitions, only allow const on the right.

If you always put/apply const on the right it helps you to think about it in the right way. This is the reason many boost libraries put const on the right.

constify apples const on the right, hence, it turns T that is int* into int* const - a constant pointer to non-constant int. And apply the reference on the right of that: int* const&.

Upvotes: 3

songyuanyao
songyuanyao

Reputation: 172884

The 1st one is correct, and the return type would be int * const &, i.e. the reference to const pointer to non-const int; not const int * &, i.e. the reference to non-const pointer to const int.

const is qualified on T itself, when T is a pointer const T would be a const pointer but not a pointer to const pointee.

Upvotes: 5

SergeyA
SergeyA

Reputation: 62553

Template type substitutions are not textual, so do not think of them in terms of the textual type definition.

In your example, T is deduced to be int * - let's call it intptr. You are making const reference to it, so return value becomes const intptr&. That means, that the pointer itself can't be modified through this reference, but the value it points to can be modified.

Last, but not the least, you could have easily verifed your assumptions before asking the question :)

Upvotes: 8

Related Questions