簡體   English   中英

Typeid運算符忽略cv限定詞的背后原理是什么

[英]What is the rationale behind the typeid operator ignoring cv-qualifiers

根據C ++語言標准(ISO / IEC 14882:2003中的§5.2.8),

左值表達式或作為typeid操作數的type-id的頂級cv限定符始終被忽略。

這個決定的理由是什么。 它在類型系統上打了一個洞,是違反直覺的。 const信息(或易失性部分)在編譯時是已知的,因此如果typeid僅考慮了cv限定詞,則不會有開銷。

盡管具有使用constvolatileconst volatile變體(請參見[class.mfct.nonstatic]),類型Dconst Dvolatile Dconst volatile D (對於某些非cv限定類型)重載非靜態成員函數的能力D )並非無關; 該標准在[basic.type.qualifier]中指定,對於每種不符合cv的類型 ,該類型都有一個具有相同表示和對齊要求的不同const限定, volatile限定和const volatile限定的“版本”。 如果Dconst D可能彼此不相關(例如,通過具有不同的表示形式,存儲要求,或者在類的情況下,具有不同的成員),則很多語言都將崩潰。

例如,類型D&的對象可以隱式轉換為const D&volatile D&const volatile D& (請參見[conv.qual])。 但是,如果允許Dconst D不相關,則此轉換將沒有意義。

還考慮一下標准中的許多地方指定了頂級cv限定詞將被忽略:

  • [over.load]指定:

    僅在存在和不存在const和/或volatile方面不同的參數聲明是等效的。 也就是說,在確定要聲明,定義或調用哪個函數時,將忽略每種參數類型的constvolatile類型說明符。

  • [temp.param]指定:

    確定模板參數的類型時,將忽略模板參數上的頂級cv限定詞

  • [basic.life]在指定如何重用其生命周期結束的對象的存儲時,提到:

    新對象與原始對象具有相同的類型(忽略頂級cv限定詞)

  • [over.best.ics]指定:

    頂級簡歷的任何差異都歸因於初始化本身,並不構成轉換。 [ 示例:類型A的參數可以從類型const A的參數初始化。 在這種情況下,隱式轉換序列是標識序列。 它不包含從const AA “轉換”。 ]

  • [temp.deduct.call]指定:

    如果A是CV-限定的類型,頂層cv修飾符A的類型被忽略類型推演。

    和:

    如果P是CV-限定的類型,頂層cv修飾符P的類型被忽略類型推演。

    ([temp.deduct.conv]使用類似的語言。)

  • [except.throw]指定:

    throw-expression會初始化一個臨時對象,該臨時對象的類型是通過從throw操作數的靜態類型中刪除所有頂級cv限定符並將“ T數組”或“返回T函數”的類型調整為“指向T指針”或“返回T函數的指針”。

  • [except.handle]指定:

    處理程序是類型為E的對象的throw-expression的匹配項,如果

    —處理程序的類型為cv Tcv T&ET是同一類型(忽略頂級cv限定詞),或…

如果允許Dconst Dvolatile Dconst volatile D是不相關的類型,則所有這些都必須更改。

因為如果操作數是多態對象,typeid返回動態類型。 Cv限定詞被設計為編譯時限制,並且必須在運行時記錄其他信息才能檢索動態類型的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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM