【问题标题】:C++ Primer 5th Edition Chapter 16.5 Class-Template SpecializationsC++ Primer 第 5 版第 16.5 章类模板专业化
【发布时间】:2021-01-19 15:50:00
【问题描述】:

我认为这本书的第 711 页有错误:

在第 16.2.3 节(第 684 页)中,我们介绍了库 remove_reference 类型。该模板通过一系列专业化工作:

// original, most general template
template <class T> struct remove_reference {
    typedef T type;
};
// partial specializations that will be used fore lvalue and rvalue references
template <class T> struct remove_reference<T&> // lvalue references
    typedef T type;
};
template <class T> struct remove_reference<T&&> // rvalue references
    typedef T type;
};

...

int i;
// declyptype(42) is int, used the original template
remove_reference<decltype(42)>::type a;
// decltype(i) is int&, uses first(T&) partial specialization
remove_reference<decltype(i)>::type b;
// delctype(std::move(i)) is int&&, uses second (i.e., T&&) partial specialization
remove_reference<decltype(std::move(i))>::type c;

abc 这三个变量的类型均为 int

我认为decltype(i) 会生成一个普通的int 而不是int&amp;,因此实际上在b 的情况下使用最通用的模板。对于普通变量类型 [1]decltype 类型说明符产生普通类型,对于其他可用作 lvalue 的表达式,它将产生 lvalue reference

示例

#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;

template <typename T> struct blubb {
    typedef T type;
    void print() { cout << "plain argument type\n"; }
};

template <typename T> struct blubb<T&> {
    typedef T type;
    void print() { cout << "lvalue reference type\n"; }
};

template <typename T> struct blubb<T&&> {
    typedef T type;
    void print() { cout << "rvalue reference type\n"; }
};

int main() {
    int i = 0;

    blubb<decltype(42)> plain;
    plain.print();
    blubb<decltype(i)> lvalue_ref; // actually not!
    lvalue_ref.print();
    
    int* pi = &i;
    blubb<decltype(*pi)> lvalue_ref2; // expression which can be on the left hand side
    lvalue_ref2.print();

    blubb<decltype(std::move(i))> rvalue_ref;
    rvalue_ref.print();

    return 0;
}

编译并运行

g++ -o types types.cpp -Wall -pedantic -g && ./types
plain argument type
plain argument type
lvalue reference type
rvalue reference type

请告诉我我是对还是错,并在适当的时候解释一下。
谢谢

[1] 可能正确的术语是id-expression

【问题讨论】:

    标签: c++ c++11 decltype errata


    【解决方案1】:

    是的,对于未加括号的 id 表达式,decltype 产生由 id 表达式命名的实体类型,然后 decltype(i) 产生类型 int

    1. 如果参数是不带括号的 id 表达式或不带括号的类成员访问表达式,则 decltype 会产生由此表达式命名的实体的类型。

    另一方面,decltype((i)) 产生int&amp; 类型; (i) 被视为左值表达式。

    1. 如果参数是T 类型的任何其他表达式,并且
      b) 如果表达式的值类别是左值,则 decltype 产生T&amp;

    请注意,如果对象的名称带有括号,则将其视为普通的左值表达式,因此decltype(x)decltype((x)) 通常是不同的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 2021-06-05
      相关资源
      最近更新 更多