以下代码
template <typename T>
struct A
{ static void f() {std::cout << "A<T>\n";} };
template <typename T>
struct A<const T>
{ static void f() {std::cout << "A<const T>\n";} };
template <typename T>
struct A<const T*>
{ static void f() {std::cout << "A<const T*>\n";} };
template <typename T>
void f()
{
A<const T>::f();
}
int main()
{
f<const int*>();
}
没有像我预期的那样工作。
我(错误地)认为
f<const int*>()
的调用调用了函数 A<const T>::f()
,在本例中是 A<const const int*>:f()
并且 const const int*
折叠成 const int*
。但这不是程序所做的,因为它打印 A<const T>
意味着 const const int*
(实际上是 const (const int*)
)折叠成 const int
。
但是为什么
const const int*
会折叠成const int
?
你的假设是错误的。
const const int*
不会“塌陷”为 const int
。
当您调用
f<const int*>()
时,您将使用 f
实例化 T = const int*
。这里, int
是 const
,所以 T = U*
其中 U = const int
。
在
f
中,您调用 A<const T>::f()
,因此您可以使用类型 A
实例化 T2 = const T = U* const
。这里,指针是const
。完整的类型是 const int * const
或 int const * const
。
因此,选择了
const T
专业化,其中 T = int const*
。 const T*
版本不太专业,因为这里的指针不是 const
。添加另一个专业使其更加清晰:
template <typename T>
struct A<const T* const>
{ static void f() {std::cout << "A<const T* const>\n";} };