2014-11-07 17 views
11

Se comprendo correttamente le regole per la durata dei temporaries, questo codice dovrebbe essere sicuro poiché la durata del temporaneo stringstream in make_string() dura fino alla fine dell'espressione completa. Non sono sicuro al 100% che non ci sia un problema sottile qui, qualcuno può confermare se questo schema di utilizzo è sicuro? Sembra funzionare bene in clang e gcc.Durata dei temporari in C++ - è sicuro?

#include <iomanip> 
#include <iostream> 
#include <sstream> 

using namespace std; 

ostringstream& make_string_impl(ostringstream&& s) { return s; } 

template<typename T, typename... Ts> 
ostringstream& make_string_impl(ostringstream&& s, T&& t, Ts&&... ts) { 
    s << t; 
    return make_string_impl(std::move(s), std::forward<Ts>(ts)...); 
} 

template<typename... Ts> 
string make_string(Ts&&... ts) { 
    return make_string_impl(ostringstream{}, std::forward<Ts>(ts)...).str(); 
} 

int main() { 
    cout << make_string("Hello, ", 5, " World!", '\n', 10.0, "\n0x", hex, 15, "\n"); 
} 
+3

Mi sembra che dovrebbe andare bene. –

+0

Tecnicamente va bene, ma credo che scoprirete che è piuttosto inefficiente. Considera solo la definizione di un generatore di stringhe con un operatore << '. –

+0

@ Cheersandhth.-Alf Dipende dal modo in cui il compilatore è in linea. – cdhowie

risposta

7

La parte rilevante dello standard è in §12.2:

12.2.3) oggetti temporanei vengono distrutti come ultimo passaggio nella valutazione pieno-espressione (1.9) che (lessicale) contiene il punto in cui sono stati creati.

Tranne:

12.2.4) Ci sono due contesti in cui provvisori vengono distrutti in un punto diverso rispetto all'estremità del pieno-espressione. Il primo contesto è quando viene chiamato un costrutto predefinito per inizializzare un elemento di un array. ... [non applicabile]

12.2.5) Il secondo contesto è quando un riferimento è associato a un temporaneo. La temporanea a cui è legato il riferimento o la temporanea che è l'oggetto completo di un oggetto secondario per cui il riferimento è legato persiste per tutta la vita del riferimento, ad esclusione:

  • ...

  • A il vincolo temporaneo a un parametro di riferimento in una chiamata di funzione (5.2.2) persiste fino al completamento dell'espressione completa che contiene la chiamata.

Così ci si va. Il temporaneo stringstream{} è associato a un riferimento in una chiamata di funzione, quindi persiste fino al completamento dell'espressione. Questo è sicuro

+0

Grazie, sembra abbastanza definitivo :) – mattnewport