模板中右值的类型推导

Posted

技术标签:

【中文标题】模板中右值的类型推导【英文标题】:Type deduction for rvalues in templates 【发布时间】:2018-12-24 23:33:36 【问题描述】:

请求一些帮助以了解右值引用的类型推导。非模板版本失败并出现以下错误,我理解原因。

错误:无法绑定“const char*&”类型的非常量左值引用 到 'const char*' 类型的右值

在 C++11 中,如果我将函数 void Firstfun(const Key& key) 更改为 void Firstfun(const Key&& key),那么它会编译,但是模板版本可以与左值引用参数一起正常工作。

至于模板化版本,我认为编译器必须生成带有右值引用的函数,因此使用__PRETTY_FUNCTION__ 对其进行了检查,但在 PRETTY_FUNCTION 的输出中没有看到它。

我确实遇到过this 讨论,其中@Anirban 提到了这些内容。

对于 wrapper(A());,类型参数 T 仍将推导出为 A, 参数 u 的类型为 A&&,称为右值引用 到A。

以下是我的问题:

    编译器如何处理模板化版本以使其接受右值? 针对非模板版本的修复void Firstfun(const Key&& key),是否有效且可接受?

非模板版本

#include <iostream>

namespace somens 

class Firstclass 
public:

    void Firstfun(const char*& key) 
        std::cout << __PRETTY_FUNCTION__ << '\n';
    
;

class Secondclass 
    Firstclass f_class;

    char* create_buf()
        char * buf = new char[10]; //buf will be freed elsewhere.
        return buf;
    

public:
    void Secondfun ()
        f_class.Firstfun(create_buf());
    

;


int main () 
  somens::Secondclass s_class;
  s_class.Secondfun();


非模板版本的输出

错误:无法绑定“const char*&”类型的非常量左值引用 到 'const char*' 类型的右值

模板版

#include <iostream>

namespace somens 
template<typename Key>
class Firstclass 
public:

    void Firstfun(const Key&  key) 
        std::cout << __PRETTY_FUNCTION__ << '\n';
    
;

class Secondclass 
    Firstclass<const char*> f_class;

    char* create_buf()
        char * buf = new char[10]; //buf will be freed elsewhere.
        return buf;
    

public:
    void Secondfun ()
        f_class.Firstfun(create_buf());
    

;


int main () 
  somens::Secondclass s_class;
  s_class.Secondfun();


模板化版本的输出

void somens::Firstclass::Firstfun(const Key&) [with Key = const 字符*]

【问题讨论】:

【参考方案1】:

您的两个 sn-ps 之间的主要区别在于,第一个采用 const char*&amp;,第二个采用 const Key&amp;(又名 Key const&amp;),其中 Keyconst char*

至关重要的是,在后一种情况下,它会为您提供一个 const char* const&amp;,它(就像对 const 的任何其他左值引用一样)可以绑定到一个临时对象。

请记住,const char* 中的 const 是无关紧要的,因为它描述的是指针,而不是指针。

您不需要模板。您只需写 using Key = const char* 就可以观察到这一点。

【讨论】:

感谢您指出 const 关键字的正确位置。指针应该是 const ,因为这就是创建引用的对象。我对错误的理解是不正确的。这里取2个,请纠正或确认我的理解。它失败的原因是因为bchar *char const* 的隐式转换导致了一个右值,这会在分配给函数参数时导致错误。 @user2914100 甚至没有发现。这是真的,但没关系,因为create_buf() 无论如何都是右值 你说得对,我在上一条评论中没有定义b。假设char * b = create_buf(); f_class.Firstfun(b);这将失败,因为从char *char const *的隐式转换,我猜...... @user2914100 我想是的 :)

以上是关于模板中右值的类型推导的主要内容,如果未能解决你的问题,请参考以下文章

C++11 学习笔记-类型推导

C++11 学习笔记-类型推导

模板别名、变量模板和自动类型推导无法推导模板参数

c++11模板类型推导规则

c++11模板类型推导规则

参数和返回类型中的模板类型推导