In the first call, when I pass a char const []
into a template function with a parameter of T const a
, T
is deduced as char const *
which is reasonable because const
refers to the decaying pointer.
However, when the parameter type is changed to T const & a
, T
is deduced as char[7]
. From the point of view above, why doesn't the const
qualify the whole array type?
template <typename T>
void show1(T const a) {
// input is const char *
// T is char const *
// a is char const * const
}
template <typename T>
void show2(T const & a) {
// input is char const [7]
// T is char[7]
// a is char const (&)[7]
}
int main() {
const char s[] = "asdasd";
show1(s);
show2(s);
}
why doesn't the
const
qualify the whole array type
Because for array type ,
(emphasis mine)
Applying cv-qualifiers to an array type (through typedef or template type manipulation) applies the qualifiers to the element type , but any array type whose elements are of cv-qualified type is considered to have the same cv-qualification.
// a and b have the same const-qualified type "array of 5 const char" typedef const char CC; CC a[5] = {}; typedef char CA[5]; const CA b = {};
That means when T
is char[7]
T const
leads to the type char const[7]
, then T const&
(ie a
's type) is char const (&)[7]
.
On the other hand, when you pass the array s
with type const char[7]
, the array is considered as const-qualified too. So given the parameter type T const&
, T
is deduced as char[7]
(but not char const[7]
).
This is because arrays are non-copyable and non-assignable in C++.
So in calling show1
, the const char[]
type decays to a const char*
. The language permits one implicit conversion per parameter at a function call site.
With show2
, you are passing by reference - no copy or assignment is required, so pointer decay does not occur.
template <typename T>
void show(ParameterType a) {
}
show(expression);
Compiler uses expression
to deduce T
and ParameterType
. T
and ParameterType
are different if ParameterType
contains qualifiers like const
.
If ParameterType
is neither pointer nor reference (case of your show1, T const
), type of T
is type of expression
without const
, volatile
and reference. So T
is type of const char *
. ParameterType
(type of a
) is const char * const
.
If ParameterType
( T const &
in your show2) is pointer or reference (but not reference like T&&
). First ignore reference, which gives results T const
(same as const T
). Second match type of expression
( const char []
) to const T
, so T
is char []
.
For more information, Item 1 of Effective Modern C++ by Scott Meyers is exactly what you want. The rule is more complicated then which I described here but very important.
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.