Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.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
什么表达式在应用decltype时生成引用类型? 我正在阅读C++的底漆,当表达式产生一个对象类型,当它给对象产生一个引用类型时,它不能理解。_C++_C++11_Decltype - Fatal编程技术网

什么表达式在应用decltype时生成引用类型? 我正在阅读C++的底漆,当表达式产生一个对象类型,当它给对象产生一个引用类型时,它不能理解。

什么表达式在应用decltype时生成引用类型? 我正在阅读C++的底漆,当表达式产生一个对象类型,当它给对象产生一个引用类型时,它不能理解。,c++,c++11,decltype,C++,C++11,Decltype,我引用书中的话: 当我们将decltype应用于一个非变量的表达式时,我们得到了该表达式产生的类型 一般来说,decltype为产生 可以位于指定左侧的对象 考虑到以下准则: int i = 3, *ptr = &i, &ref = i; decltype(ref + 0) j; 在上述代码中,表达式“ref+0”导致对ref所指对象的值i和0进行相加的固有操作。因此,按照第一条规则,表达式将生成int类型。 但是按照第二条规则,由于表达式生成的对象类型可以位于赋值的左侧(在本

我引用书中的话:

  • 当我们将decltype应用于一个非变量的表达式时,我们得到了该表达式产生的类型
  • 一般来说,decltype为产生 可以位于指定左侧的对象
  • 考虑到以下准则:

    int i = 3, *ptr = &i, &ref = i;
    decltype(ref + 0) j;
    
    在上述代码中,表达式“ref+0”导致对ref所指对象的值i和0进行相加的固有操作。因此,按照第一条规则,表达式将生成int类型。 但是按照第二条规则,由于表达式生成的对象类型可以位于赋值的左侧(在本例中为int),decltype不应该生成ref-to-int(int&)类型吗

    书中还说,对于以下代码

    decltype(*ptr) k;
    
    k的类型是int&而不是int,表达式产生的类型

    它还表示,对于下面代码中的赋值表达式

    decltype(a = b) l;
    
    l将具有赋值操作左侧对象的引用类型


    我们如何知道哪些表达式产生对象类型,哪些表达式产生对对象类型的引用?

    对于表达式,如示例中所示,如果参数为左值,decltype将提供引用类型

    7.1.6.2p4:

    The type denoted by decltype(e) is defined as follows:
      — if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e)     is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions,     the program is ill-formed;
      — otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
      — otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
      — otherwise, decltype(e) is the type of e.
    The operand of the decltype specifier is an unevaluated operand (Clause 5).
    [ Example:
    const int&& foo();
    int i;
    struct A { double x; };
    const A* a = new A();
    decltype(foo()) x1 = i; // type is const int&&
    decltype(i) x2; // type is int
    decltype(a->x) x3; // type is double
    decltype((a->x)) x4 = x3; // type is const double&
    —end example ]
    

    要理解这些概念而不正式是不容易的。初级读物可能不想让您感到困惑,并且避免引入诸如“左值”、“右值”和“xvalue”之类的术语。不幸的是,为了理解
    decltype
    的工作原理,这些都是基础

    首先,求值表达式的类型决不是引用类型,也不是顶级
    const
    -非类类型的限定类型(例如
    int-const
    int&
    )。如果表达式的类型被证明是
    int&
    int const
    ,则在进一步计算之前,它会立即转换为
    int

    这在C++11标准的第5/5和5/6段中有规定:

    5如果表达式最初具有类型“引用T”(8.3.2,8.5.3),则该类型在 任何进一步的分析。表达式指定由引用表示的对象或函数,以及 表达式是左值或X值,具体取决于表达式

    6如果prvalue最初的类型为“cv T”,其中
    T
    是cv非限定非类、非数组类型,则 在进一步分析之前,将表达式调整为
    T

    表达就到此为止。
    decltype
    做什么?确定给定表达式
    e
    decltype(e)
    结果的规则在第7.1.6.2/4段中规定:

    decltype(e)
    表示的类型定义如下:

    -如果
    e
    是未加密的id表达式或未加密的类成员访问(5.2.5),
    decltype(e)
    是由
    e
    命名的实体的类型。如果没有这样的实体,或者如果
    e
    命名了一组重载函数, 该计划形式不合理

    -否则,如果
    e
    是一个x值,
    decltype(e)
    T&
    ,其中
    T
    e
    的类型

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

    -否则,
    decltype(e)
    e
    的类型

    decltype
    说明符的操作数是未赋值的操作数(第5条)

    这听起来确实令人困惑。让我们试着一部分一部分地分析它。首先:

    -如果
    e
    是未加密的id表达式或未加密的类成员访问(5.2.5),
    decltype(e)
    是由
    e
    命名的实体的类型。如果没有这样的实体,或者如果
    e
    命名了一组重载函数, 该计划形式不合理

    这很简单。如果
    e
    只是一个变量的名称,而您没有将其放在括号内,则
    decltype
    的结果就是该变量的类型。所以

    bool b; // decltype(b) = bool
    int x; // decltype(x) = int
    int& y = x; // decltype(y) = int&
    int const& z = y; // decltype(z) = int const&
    int const t = 42; // decltype(t) = int const
    
    请注意,这里的
    decltype(e)
    的结果不一定与计算表达式
    e
    的类型相同。例如,表达式
    z
    的求值产生类型为
    int const
    ,而不是
    int const&
    (因为在第5/5段中,
    &
    被剥离,正如我们前面所看到的)

    让我们看看当表达式不仅仅是标识符时会发生什么:

    -否则,如果
    e
    是一个x值,
    decltype(e)
    T&
    ,其中
    T
    e
    的类型

    这越来越复杂了。什么是xvalue?基本上,它是表达式可以属于的三个类别之一(xvalue、lvalue或prvalue)。当调用返回类型为右值引用类型的函数时,或者作为对右值引用类型进行静态转换的结果时,通常会获得xvalue。典型的例子是调用
    std::move()

    使用标准中的措辞:

    [注意:如果表达式是:

    -隐式或显式调用返回类型为右值引用的函数的结果 对于对象类型

    -对对象类型的右值引用的强制转换

    -一种类成员访问表达式,指定非引用类型的非静态数据成员,其中 对象表达式是一个xvalue,或

    -a公司
    int x; // decltype(std::move(x)) = int&&
           // decltype(static_cast<int&&>(x)) = int&&
    
    int x; // decltype(x) = int (as we have seen)
           // decltype((x)) = int& - here the expression is parenthesized, so the
           // first bullet does not apply and decltype appends & to the type of
           // the expression (x), which is int
    
    int& foo() { return x; } //  decltype(foo()) = int& 
    
    int foo() { return x; } // Function calls for functions that do not return
                            // a reference type are prvalue expressions
    
    // decltype(foo()) = int
    // decltype(42) = int
    
    int i = 3, *ptr = &i, &ref = i;
    decltype(ref + 0) j;
    decltype(*ptr) k;
    decltype(a = b) l;
    
    int foo() { return 42; }
    
    foo() = 24; // ERROR! foo() is a prvalue expression, cannot be on the left
                // side of an assignment