【问题标题】:Template type deduction of const reference typeconst引用类型的模板类型推导
【发布时间】:2020-07-26 07:15:39
【问题描述】:

当使用对模板参数类型的 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 &amp;a(顶级常量);但是如果我们直接替换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 的类型是什么;

【问题讨论】:

  • const T &amp;a 显然是“对 T 的 const 引用”。如果将const int* 传递为T 会不会很奇怪和令人惊讶,突然​​你会得到“对T 的非常量引用,其中T 是const int*”?我会觉得这很违反直觉。

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


【解决方案1】:

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

在第二种情况下,最终类型是“不能用于更改其所指对象的引用,它是指向整数的指针,并且该指针不能用于更改整数。”所以*a就是const int,不能修改。

【讨论】:

    【解决方案2】:

    第一种情况

    如果我们直接将T 替换为int*,我们会得到const int* &amp;a(一个低级常量)并且编译器应该会失败。

    不是真的……

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

    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*

    【讨论】:

    • 在声明中T const &amp; 是否比const T &amp; 更受欢迎?我知道它是 'T​​ const &'; 格式的低级 const
    • 不,两者都不是首选。或者更确切地说 - 这是一场“宗教”辩论......另见:Const before or const after?。至于“低级常量” - 没有这样的术语。也就是说,我从未听说过。问题只是 const 适用于什么构造。 C 语法与其规则有点混淆;而且你不能总是用(括号)来澄清,因为它们也被用来声明一个函数。
    • 嗯,我引用了 C++ 入门中的“低级 const”,请参见:cplusplus.com/forum/beginner/143366;现在,我的问题更多是关于格式;这可能根本没有意义;但我的问题是:如果在模板中,我们以const T &amp;的格式声明参数,它怎么会变成int* const &amp;?这两种形式不匹配。
    • 只是不要将模板实例化视为纯粹的文本复制粘贴。模板类型是“对常量 T 的引用”。如果 T 是“指向 int 的指针”,则实例化的模板是“对指向 int 的常量指针的引用”。好像 T 是“盒装”的。
    • @Marcus_Ma:好的,我收回我之前的评论。显然,这些术语之一已正式引入 C++17 标准。根据我的经验,它们仍然很少使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    相关资源
    最近更新 更多