Come spiegato in questa domanda, un effetto di
#include <iostream>
è l'equivalente di definire una variabile globale
static std::ios_base::Init __init;
che (supponendo che si include all'inizio del TU) garanzie che per tutti gli oggetti di durata di archiviazione statica con ordinati nell'inizializzazione nella stessa TU, gli oggetti di flusso sono stati impostati.
specializzazioni template Tuttavia, esplicitamente e implicitamente esemplificati hanno ordinata inizializzazione ([basic.start.dynamic]/1) :
inizializzazione dinamica di una variabile non locale con statico stoccaggio durata è ordinata se la variabile è un implicitamente o esplicitamente specializzazione istanziata, e in caso contrario è ordinata [nota omessa]. Le variabili con inizializzazione ordinata definite all'interno di una singola unità di traduzione devono essere inizializzate nell'ordine delle loro definizioni nell'unità di traduzione.
E poiché
Se un programma viene avviato un thread, la successiva inizializzazione non ordinato di una variabile è non in sequenza rispetto ad ogni altra inizializzazione dinamica. In caso contrario, l'inizializzazione non ordinata di una variabile è sequenzialmente indeterminata rispetto ad ogni altra inizializzazione dinamica .
non c'è alcuna garanzia che gli oggetti stream sono stati inizializzati al momento il modello di specializzazione variabile x<Test>
viene inizializzata.
In questo caso, poiché una delle possibili esecuzioni risulta in un comportamento non definito (utilizzando gli oggetti flusso prima che siano inizializzati), il comportamento dell'intero programma non è definito (vedere [intro.execution]/5).
La correzione è quello di costruire un oggetto std::ios_base::Init
te stesso nel costruttore Test
s'.
Questo è in realtà underspecified per i modelli di variabili quando C++ 14 è stato pubblicato, ma è sempre stato l'intento.
fonte
2016-06-08 15:06:28
Funziona con GCC. Forse è un bug in clang? – Cornstalks
@Cornstalks Forse. Ma forse è solo un comportamento non specificato? – FrozenHeart