Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板参数推导和表达式规则_C++_Templates_Language Lawyer_C++20 - Fatal编程技术网

C++ 模板参数推导和表达式规则

C++ 模板参数推导和表达式规则,c++,templates,language-lawyer,c++20,C++,Templates,Language Lawyer,C++20,关于这一点,我有一个后续问题: 注释P和A请参阅本节 如果我正确理解模板参数推断,以下代码将发生以下情况: 模板 void foo(const T&a); int b; foo(std::move(b)); 首先,编译器分别为参数声明和模板参数推导出两种类型P和A。当声明是一个引用常量&(但不是转发引用)时,我们将对这种情况进行推导 对于A:std::move(b)具有调整为A:=int() 对于P:const T&->删除const和reference([])->P:=T 模式匹配A与P-

关于这一点,我有一个后续问题: 注释
P
A
请参阅本节 如果我正确理解模板参数推断,以下代码将发生以下情况:

模板
void foo(const T&a);
int b;
foo(std::move(b));
  • 首先,编译器分别为参数声明和模板参数推导出两种类型
    P
    A
    。当声明是一个引用
    常量&
    (但不是转发引用)时,我们将对这种情况进行推导
  • 对于
    A
    std::move(b)
    具有调整为
    A:=int
    ()
  • 对于
    P
    const T&
    ->删除const和reference([])->
    P:=T
  • 模式匹配
    A
    P
    ->结果
    T:=int
两个问题:

  • 所描述的程序准确吗
  • std::move(b)
    是一个表达式,我一直认为它的类型是
    int&
    (因为
    std::move
    返回一个
    int&&
    ),但是()告诉了一些不同的东西,这意味着在任何分析发生之前删除每个引用,所以当我们谈论表达式的类型时,从未涉及任何参考:
  • struct A{A&operator+(const A&);}
    A,b;
    自动c=a+b;
    
    因此
    a+b
    显然返回a
    a&
    。但是表达式的类型是
    A
    。对吗
    declval(a+b)
    是另一个野兽,返回
    a&

  • 所描述的程序是准确的
  • 引用将从表达式类型中删除。但表达式会获得另一个属性,即值类别,该属性映射到函数调用表达式的引用类型:

    如果结果类型是对函数类型的左值引用类型或右值引用,则函数调用为左值;如果结果类型是对对象类型的右值引用,则函数调用为xvalue;否则为prvalue

  • 这几乎可以用推理规则来表示:

    function return type             function call expression [type,value-category]
         T&                  =>        [ T , lvalue ]
         T&&                 =>        [ T , xvalue ]
         T                   =>        [ T , prvalue ]
    
    decltype
    进行反向映射:

    对于表达式e,decltype(e)表示的类型定义如下:

    • [……]
    • 否则,如果e是xvalue,decltype(e)是T&&,其中T是e的类型

    • 否则,如果e是左值,decltype(e)是T&,其中T是e的类型

    • 否则,decltype(e)就是e的类型


    因此,在[expr.type]中删除引用不会丢失引用带给类型的信息。此信息由值类别表示。

    A&operator+(const A&)看起来很奇怪。不一定违法,但肯定很奇怪。这对你的问题并不重要。我知道,回信不是很好,这显然是错误的,但只是作为一个例子来证明我的观点。:)有一些关于引用表达式如何工作的信息
    declval(…)
    出于同样的原因不返回引用类型。仍然让我困惑的是:
    int&&a;a表达式的类型是什么
    a。它是一个
    id表达式
    并且它的类型是
    int&
    ?@Gabriel,
    a
    的类型与它的声明中指定的类型完全相同:
    int&
    。(其价值类别为左值。)@Gabriel。id表达式总是左值。表达式
    a
    的类型为
    int
    ,值类别为
    lvalue
    。分离变量的声明类型和仅为该变量名称的表达式类型的概念非常重要。也许这个Q&A会有所帮助:所以你基本上参考了for
    decltype(A)
    。这是正确的吗?@Gabriel我的意思是
    decltype(a)
    不提供id表达式
    a
    的类型和值类别的信息,但提供id表达式
    a
    表示的变量类型的信息(声明的
    a
    )。