基本模板问题:“const const int*”在“const int”中的衰减

Basic template question: `const const int*` decay in `const int`

提问人:Antonio 提问时间:9/29/2023 更新时间:9/29/2023 访问量:85

问:

以下代码

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

C++ 模板 元编程

评论

3赞 Jarod42 9/29/2023
const T是 (或 )。int const* constconst int* const
1赞 Marek R 9/29/2023
吹毛求疵:术语“衰减”是指数组衰减到指向该数组中第一个值的指针。
1赞 Marek R 9/29/2023
godbolt.org/z/bdqhq35ac
0赞 Sam Varshavchik 9/29/2023
不,这不是因为“const const int* collapses into const int*”。你在哪里看到这里?第三个模板更专业,因此被选中,并推断为 。const const int *Tint
0赞 Nelfeal 9/29/2023
@SamVarshavchik 这是一个非常糟糕的复制品。OP 的问题不在于哪个模板更专业。此外,第二个模板更专业,而不是第三个模板:它打印 ."A<const T>"

答:

5赞 Nelfeal 9/29/2023 #1

你的假设是错误的。 不会“坍缩”成.const const int*const int

调用 时,使用 进行实例化。这里,是 ,所以在哪里。f<const int*>()fT = const int* = int const*intconstT = U*U = const int = int const

在 中,你调用 ,所以你用一个类型进行实例化。此处,指针是 。完整的类型是 或 。从来没有.fA<const T>::f()AT2 = const T = U* constconstconst int * constint const * constconst const int*

因此,选择了专业化,其中 .该版本不太专业,因为它是指向 的指针,而不是指针。添加另一个专业化可以更清楚地说明:const TT = int const*const T*const Tconst

template <typename T>
struct A<const T* const>
{ static void f() {std::cout << "A<const T* const>\n";} };

演示

3赞 Miles Budnek 9/29/2023 #2

如果您反转展示位置,则更容易理解这种情况。也就是说,对于任何类型,都等价于 。事实上,这是“正常”的使用方式。通常适用于其左侧的类型。特殊情况是,if 是类型中的第一个单词,它直接应用于其右侧的类型,但这种特殊情况可能会使模板有点混乱。constTconst TT constconstconstconst

所以等价于 。请注意,它是 that's ,而不是指针:表示“指向常量的非常量指针”。f<const int*>()f<int const*>()intconstint const*int

在 中,由于等价于 和 是 ,变为:“指向常量的常量指针”。f<int const*>()const TT constTint const*T constint const* constint

没有可以匹配的类型,因此部分专业化是不可行的。TT const*int const* constA