2014-08-27 3 views
13

Affinché un tipo possa "suonare bene" con le librerie standard C++ 03, è stata considerata una cattiva idea sovraccaricare lo operator&() poiché l'indirizzo era necessario per utilizzare correttamente il tipo e l'overloading ha creato problemi imprevisti; l'esempio classico qui è ATL::CComBSTR.Lo std :: addressof annulla l'operatore e il requisito STL?

  • Con l'avvento di std::addressof() in C++ 11 e su, fa questo nega che il vecchio requisito (s) sui tipi in uso nella libreria standard?
  • Il requisito è esplicitamente enunciato (o rimosso dallo standard in C++ 11, vale a dire la libreria standard richiesta dalla specifica per utilizzare std::addressof()?
+2

Quale "requisito" in C++ 03? Sei sicuro che fosse un * requisito * e non una * raccomandazione *? – Rapptz

+3

Cosa c'è di sbagliato in CComBSTR? –

+0

@Rapptz, vero, non sono sicuro che fosse obbligatorio come requisito, ma se sovraccarico su 'operatore &' il tipo e il STL non rendevano buoni "compagni di letto". – Niall

risposta

8

Lo value_type di un contenitore ha solo alcuni requisiti. Dipendono principalmente dal container, ma nel caso generale i requisiti sono almeno MoveConstructible e MoveAssignable.

Guardando le C++ 11 tavoli standard per che cosa significano questi requisiti, si ottiene questo:

§ 17.6.3.1 Tabella 20 (MoveConstructible):

+----------------------------------------------------------+ 
| Expression   |  Post Condition    | 
|----------------------------------------------------------+ 
| T u = rv;   | u is equivalent to the    | 
|     | value of rv before the construction | 
+----------------------------------------------------------+ 
| T u(rv);   | T(rv) is equivalent to the   | 
|     | value of rv before the construction | 
+----------------------------------------------------------+ 
| rv's state is unspecified.        | 
|               | 
+----------------------------------------------------------+ 

§ 17.6.3.1 Tabella 22 (MoveAssignable).

+-----------+--------------+-------------+----------------------+ 
    | Expression| Return Type | Return value| Post Condition  | 
    |-----------|--------------|-------------|----------------------| 
    | t = rv; | T&   | t   | t is equivalent to | 
    |   |    |    | the value of rv  | 
    |   |    |    | before the assignment| 
    |   |    |    |      | 
    +---------------------------------------------------------------+ 
    | rv's state is unspecified          | 
    |                | 
    +---------------------------------------------------------------+ 

Non ci sono altri requisiti indicati in un contenitore a seconda di quello che è, come DefaultConstructible. Tuttavia, nessuno dei requisiti richiede che operator& non sia sovraccaricato. Si occupano principalmente della costruibilità di value_type anziché dei sovraccarichi dell'operatore forniti dal tipo.

Le altre tabelle sono disponibili al § 17.6.3.1. I requisiti del contenitore sono specificati sopra al § 23.

5

Il C++ 03 CopyConstructible requisiti inclusi esplicitamente il requisito che l'operatore di indirizzo restituito l'indirizzo reale dell'oggetto, come indicato nelle osservazioni § 20.1 .3 (Tabella 30), quindi i tipi che hanno sovraccaricato quell'operatore potrebbero incontrare problemi con la libreria standard.

+------------+-------------+--------------------------+ 
| expression | return type | requirement    | 
+------------+-------------+--------------------------+ 
| T(t)  |    | t is equivalent to T(t) | 
+------------+-------------+--------------------------+ 
| T(u)  |    | u is equivalent to T(u) | 
+------------+-------------+--------------------------+ 
| t.~T()  |    |       | 
+------------+-------------+--------------------------+ 
| &t   | T*   | denotes the address of t | 
+------------+-------------+--------------------------+ 
| &u   | const T* | denotes the address of u | 
+------------+-------------+--------------------------+ 

C++ 11 semplifica il movimento (e copiare definizioni costruibili e assegnabili) ad una sintassi più semplice;

T (rvalue); // move construct 
T u = rvalue; // move assign 
T (value); // copy construct 
T u = value; // copy assign 

Non fa alcuna menzione dell'indirizzo sovraccarico dell'operatore, ma anche fare menzione di poco std::addressof esplicitamente che sia necessario (fuori da alcune .resize() funzioni). std::allocator tuttavia richiede esplicitamente che l'indirizzo dei tipi sia corretto anche in presenza di sovraccarico operator&().

In conclusione, è possibile che ci sia poco nelle specifiche per richiedere l'uso di std::addressof() ma alla luce dei requisiti semplificati e dei requisiti di indirizzo esplicito dell'oggetto; l'uso di std::addressof() (o simile) è molto vicino al mandato.

Il mio take-away qui è; se stai scrivendo il codice generico e richiedi l'indirizzo di un oggetto, usa std::addressof() e continua a stare dalla parte della sicurezza.

+0

Evidenzia qui le differenze tra C++ 03 e C++ 11. – Niall