La risposta che dà Andy Prowl è corretta. Volevo commentare l'implementazione di libC++ e il formato dei commenti non mi permette di scegliere abbastanza spazio o opzioni di formattazione.
Daniel Krügler ed io abbiamo avuto una conversazione circa un anno fa su questo argomento, e mi ha convinto che questo problema era degno di inserire un'estensione in libC++ per ottenere esperienza sul campo. E finora il feedback è stato positivo. Tuttavia, voglio chiarire: non è così semplice come rimuovere explicit
dal ctor explicit constexpr tuple(UTypes&&...)
.
Il piano di Daniel è quello di dare a tuple
un costruttore che rispetti perfettamente la costruzione implicita/esplicita di ogni elemento. E se ogni elemento verrà costruito implicitamente da ogni argomento nell'elenco di inizializzazione, quindi la costruzione della tupla è implicita, altrimenti sarà esplicita.
Ad esempio:
Data:
#include <tuple>
struct A
{
};
struct B
{
B() = default;
B(A);
};
struct C
{
C() = default;
explicit C(A);
};
Poi:
std::tuple<>
test0()
{
return {}; // ok
}
Non c'è molto da dire su quello. Ma anche questo è ok:
std::tuple<B>
test1B()
{
return {A()}; // ok B(A) implicit
}
perché la conversione A
-B
è implicita. Tuttavia il seguente è un errore di compilazione:
std::tuple<C>
test1C()
{
return {A()}; // error, C(A) is explicit
}
perché la conversione A
-C
è esplicito. Questa logica continua per le tuple a più elementi. Per una conversione implicita accada, ogni elemento deve avere una conversione implicita dalla lista degli argomenti:
std::tuple<A, B>
test2B()
{
return {A(), A()}; // ok each element has implicit ctor
}
std::tuple<A, C>
test2C()
{
return {A(), A()}; // error, C(A) is explicit
}
vorrei sottolineare: Si tratta di un'estensione libC++ in questo momento.
Aggiornamento
chico ha fatto un buon suggerimento che aggiorno questa risposta:
Dal momento che questa risposta è stata data, Daniel Krugler ha scritto un paper e lo ha presentato al comitato di C++ a Bristol lo scorso aprile. Sebbene il documento sia stato ben accolto, è stato rivisto troppo tardi nella settimana per votarlo nell'attuale bozza di lavoro.
Aggiornamento
la proposta di Daniel è ora parte del current working draft. L'implementazione di libC++ ora è impostata per diventare standard in questo senso per il prossimo standard C++ (C++ 17 speriamo).
Basta commentare la tua ultima domanda: No, non è lo stesso. Una dichiarazione di ritorno è un contesto di "inizializzazione della copia" mentre il tuo ultimo esempio è in realtà una "inizializzazione diretta". La differenza tra entrambi è che per l'inizializzazione della copia vengono considerati solo costruttori non espliciti. – sellibitze
Anche Visual Studio 14 Update 3 lo accetta. – Liviu