const引用类型的模板类型推导

时间:2020-07-26 07:15:39

标签: c++ function-templates const-reference

当使用const引用模板参数类型时,C ++ 11如何进行模板推导使我有些困惑。考虑以下程序:

template <typename T> void test_func(const T &a){
    (*a)++; 
}

int main() {
    // 1st case
    int i = 1;
    test_func(&i); 
    
    // 2nd case
    const int* cPtr = &i; 
    test_func(cPtr); 
}

我的问题是:

  • 对于第一种情况,它可以很好地编译;因此,似乎实例化的模板函数参数是int* const &a(顶级const);但是,如果我们直接替换T with int * , we get const int *&a`(低级const),则编译器应该会失败;我们如何以“ const T&a”的格式表示底层const?我很困惑参数的实类型是什么,T的类型是什么?
  • 对于第二种情况,编译失败并显示
    error: increment of read-only location `*(const int*)a;'
    
    似乎第二个实例化函数也继承了底层const;那么参数的类型是什么? T是什么类型?

2 个答案:

答案 0 :(得分:3)

您的test_func()收到对某些内容的const引用。在第一种情况下,something是整数的地址,因此最终类型是“不能用于更改其指向整数的指针的引用”。这意味着您可以使用指向整数的指针,包括使用它来更改整数,但不能将指针的值(即地址)更改为指向其他对象。

在第二种情况下,最终类型是“不能用于更改其引用的引用,该引用是指向整数的指针,并且该指针不能用于更改整数”。因此,*aconst int,无法修改。

答案 1 :(得分:2)

第一种情况

如果我们直接将T替换为int*,则会得到const int* &a(低级const),编译器应该会失败。

不是真的...

问题是,C ++(后跟C)在声明变量时语法有些复杂,“直接替换”并不意味着“简单复制粘贴”。就您而言,假设您将声明重写为T const&。现在,如果您复制粘贴,您将得到:

void test2(int * const &a){
    (*a)++; 
}

应该可以编译,并且可以编译。

第二种情况

T是什么类型?

让我们检查一下!在回答以下问题后:Print template typename at compile time

我们写:

template <typename T> void test_func(T const &a){
    bool x = T::nothing; 
    (*a)++; 
}

int main() {
    int i = 1;
    // 2nd case
    const int* cPtr = &i; 
    test_func(cPtr);     
}

当我们run this program时,我们得到:

source>: In instantiation of 'void test_func(const T&) [with T = const int*]':
<source>:10:19:   required from here
<source>:2:17: error: 'nothing' is not a member of 'const int*'
    2 |     bool x = T::nothing;
      |                 ^~~~~~~

因此,在这种情况下,Tconst int*