typeid运算符忽略cv限定符的基本原理是什么 < >从C++语言标准,从ISO/IEC 1488~2003中引用5.2.8,引用,

typeid运算符忽略cv限定符的基本原理是什么 < >从C++语言标准,从ISO/IEC 1488~2003中引用5.2.8,引用,,c++,typeid,typeinfo,C++,Typeid,Typeinfo,左值表达式的顶级cv限定符或typeid的操作数类型id始终被忽略 这一决定的理由是什么。它在打字系统上打了一个洞,这是违反直觉的。常量信息(或易失性部分)在编译时是已知的,因此如果typeid只考虑cv限定符,就不会有开销。尽管可以使用const、volatile和const volatile变量重载非静态成员函数(请参见[class.mfct.nonstatic]),类型D,const D,volatile D,和const volatile D(对于某些非cv限定类型D)并非无关;本标准在

左值表达式的顶级cv限定符或typeid的操作数类型id始终被忽略


这一决定的理由是什么。它在打字系统上打了一个洞,这是违反直觉的。常量信息(或易失性部分)在编译时是已知的,因此如果typeid只考虑cv限定符,就不会有开销。

尽管可以使用
const
volatile
const volatile
变量重载非静态成员函数(请参见[class.mfct.nonstatic]),类型
D
const D
volatile D
,和
const volatile D
(对于某些非cv限定类型
D
)并非无关;本标准在[basic.type.qualifier]中规定,对于每个cv不合格类型,都有一个具有相同表示和对齐要求的不同类型的
const
-qualified、
volatile
-qualified和
const volatile
-qualified“版本”。如果
D
const D
可能彼此不相关(例如,通过具有不同的表示、存储要求,或者在类的情况下,具有不同的成员),那么许多语言都会崩溃

例如,类型为
D&
的对象可以隐式转换为
const D&
volatile D&
const volatile D&
(请参见[conv.qual])。但是,如果允许
D
const D
无关,则此转换没有意义

还要考虑标准中的许多地方指定忽略顶级cv限定符:

  • [过载]指定:

    仅在存在或不存在
    const
    和/或
    volatile
    时不同的参数声明是等效的。也就是说,在确定要声明、定义或调用哪个函数时,忽略每个参数类型的
    const
    volatile
    类型说明符

  • [温度参数]指定:

    在确定模板参数的类型时,将忽略模板参数上的顶级cv限定符

  • [basic.life]在指定如何重用生命周期结束的对象的存储时提到:

    新对象与原始对象的类型相同(忽略顶级cv限定符)

  • [over.best.ics]指定:

    顶级cv资格认证中的任何差异均包含在初始化中,不构成转换。[示例:
    a
    类型的参数可以从
    const a
    类型的参数初始化。这种情况下的隐式转换序列是标识序列;它不包含从
    const a
    a
    的“转换”]

  • [临时扣减调用]指定:

    如果
    A
    是cv限定类型,则在类型扣除时忽略
    A
    类型的顶级cv限定符

    以及:

    如果
    p
    是cv限定类型,则在类型扣除时忽略
    p
    类型的顶级cv限定符

    ([temp.Decrete.conv]具有类似的语言。)

  • [except.throw]指定:

    throw表达式初始化临时对象,其类型是通过从
    throw
    的操作数的静态类型中删除任何顶级cv限定符,并将类型从“T数组”或“返回
    T
    的函数”调整为“指向
    T
    的指针”来确定的;或分别指向返回
    T
    的函数的指针

  • [except.handle]指定:

    处理程序与类型为
    E
    if的对象的抛出表达式匹配

    -处理程序的类型为cv
    T
    或cv
    T&
    E
    T
    是同一类型(忽略顶级cv限定符),或


如果允许
D
const D
volatile D
const volatile D
为不相关类型,则所有这些都必须更改。

因为
typeid
在操作数为a时返回动态类型。Cv限定符被设计为编译时间限制,必须记录附加信息rded在运行时检索动态类型的cv限定符,因此忽略顶级cv限定符是合理的

对于类型或非多态对象的操作数,
typeid
忽略一致性的顶级cv限定符。否则,例如,以下
assert
将意外触发:

struct Base {
    virtual ~Base() {}
};

struct Derived : public Base {};

const Derived *d = new Derived;
const Base *b = d;

assert(typeid(*b) == typeid(decltype(*d))); // should not fire

因此,对于那些抱怨RTTI膨胀的人,您的反应是生成四倍的数据?您可以使用
decltype
进行编译时分析;RTTI的要点是进行无法在编译时确定的运行时分析-time@M.M引用“注意,这是N1607中提出的规则的改变,其中CV限定符,或者L或Rouple对DeCype结果没有贡献。”(来自N1705)。CV限定符与C++的其他部分很好地匹配是不容易的。然而,F(t&)和f(const t&)是不同的函数。为了保持一致,这两个应该被认为是相同的。然后我们可以一致地说cv限定符不引入子类型,它们只引入和属性到该类型的特定对象。它们当然是不同的类型。您第2段中的逻辑也不好;
派生的&
可以隐式转换但我怀疑是否有人会认为这没有意义,或者它们是同一类型。派生表示基的一个子类型,使派生和隐式转换为基&正如预期的那样。考虑函数f(int)、f(const int)、f(int&)a