简体   繁体   中英

Why is type deduction on const char[] different to const char *?

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.

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