为什么 const char[] 的类型推导不同于 const char *?
Why is type deduction on const char[] different to const char *?
在第一次调用中,当我将 char const []
传递给参数为 T const a
的模板函数时,T
被推断为 char const *
这是合理的,因为const
指的是衰减指针。
但是,当参数类型更改为T const & a
时,T
被推导为char[7]
。从上面的观点来看,为什么 const
没有限定整个数组类型?
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
因为 array type,
(强调我的)
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 = {};
这意味着当T
是char[7]
时T const
导致类型char const[7]
,那么T const&
(即a
的类型) 是 char const (&)[7]
.
另一方面,当您传递类型为 const char[7]
的数组 s
时,该数组也被视为 const-qualified。因此给定参数类型 T const&
,T
被推断为 char[7]
(但不是 char const[7]
)。
这是因为数组在 C++ 中是 non-copyable 和 non-assignable。
因此在调用 show1
时,const char[]
类型衰减为 const char*
。该语言允许在函数调用站点对每个参数进行一次隐式转换。
使用 show2
,您通过引用传递 - 不需要复制或赋值,因此不会发生指针衰减。
template <typename T>
void show(ParameterType a) {
}
show(expression);
编译器使用 expression
推导 T
和 ParameterType
。如果 ParameterType
包含诸如 const
.
之类的限定符,则 T
和 ParameterType
是不同的
如果 ParameterType
既不是指针也不是引用(你的 show1 的情况,T const
),T
的类型是没有 const
的 expression
的类型, volatile
和参考。所以 T
是 const char *
的类型。 ParameterType
(a
的类型)是 const char * const
。
如果 ParameterType
(您的 show2 中的 T const &
)是指针或引用(但不是像 T&&
那样的引用)。首先忽略引用,它给出结果 T const
(与 const T
相同)。 expression
(const char []
) 到 const T
的第二个匹配类型,所以 T
是 char []
.
更多信息,Item 1 of Effective Modern C++ by Scott Meyers正是您想要的。规则比我在这里描述的更复杂,但非常重要。
在第一次调用中,当我将 char const []
传递给参数为 T const a
的模板函数时,T
被推断为 char const *
这是合理的,因为const
指的是衰减指针。
但是,当参数类型更改为T const & a
时,T
被推导为char[7]
。从上面的观点来看,为什么 const
没有限定整个数组类型?
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
因为 array type,
(强调我的)
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 = {};
这意味着当T
是char[7]
时T const
导致类型char const[7]
,那么T const&
(即a
的类型) 是 char const (&)[7]
.
另一方面,当您传递类型为 const char[7]
的数组 s
时,该数组也被视为 const-qualified。因此给定参数类型 T const&
,T
被推断为 char[7]
(但不是 char const[7]
)。
这是因为数组在 C++ 中是 non-copyable 和 non-assignable。
因此在调用 show1
时,const char[]
类型衰减为 const char*
。该语言允许在函数调用站点对每个参数进行一次隐式转换。
使用 show2
,您通过引用传递 - 不需要复制或赋值,因此不会发生指针衰减。
template <typename T>
void show(ParameterType a) {
}
show(expression);
编译器使用 expression
推导 T
和 ParameterType
。如果 ParameterType
包含诸如 const
.
T
和 ParameterType
是不同的
如果 ParameterType
既不是指针也不是引用(你的 show1 的情况,T const
),T
的类型是没有 const
的 expression
的类型, volatile
和参考。所以 T
是 const char *
的类型。 ParameterType
(a
的类型)是 const char * const
。
如果 ParameterType
(您的 show2 中的 T const &
)是指针或引用(但不是像 T&&
那样的引用)。首先忽略引用,它给出结果 T const
(与 const T
相同)。 expression
(const char []
) 到 const T
的第二个匹配类型,所以 T
是 char []
.
更多信息,Item 1 of Effective Modern C++ by Scott Meyers正是您想要的。规则比我在这里描述的更复杂,但非常重要。