2015-11-23 14 views
5

Secondo lo C++ Core Guidelines, dovrei use a gsl::span to pass a half-open sequence.Perché non riesco a costruire un gsl :: span con un elenco di inizializzazione racchiuso tra parentesi

penso che significa che invece di scrivere una funzione come:

void func(const std::vector<int>& data) { 
    for (auto v : data) std::cout << v << " "; 
} 

dovrei preferire:

void func(gsl::span<const int> data) { 
    for (auto v : data) std::cout << v << " "; 
} 

che ha il vantaggio di non assumere il chiamante ha i propri dati in un vector, o obbligarli a costruire un valore temporaneo vector. Potrebbero passare un std::array per esempio.

Ma un caso d'uso comune è quello di passare una doppietta chiuso in lista di inizializzazione:

func({0,1,2,3}) 

Questo funziona per una funzione di prendere una std::vector ma per una funzione di prendere una gsl::span ricevo il seguente messaggio di errore:

errore C2664: 'func void (GSL :: arco)': non è in grado di convertire argomento 1 da 'inizializzazione-list' a 'gsl :: arco'

Sembra gsl::spanhas a templated constructor progettato per prendere qualsiasi contenitore.

Si tratta di qualcosa che manca nell'implementazione di Microsoft GSL o c'è una buona ragione per impedire questa pratica?

+1

Un elenco rinforzato non è un contenitore. –

+0

@KerrekSB È un 'std :: initializer_list' un contenitore? – user3467895

+2

No, non lo è. È un tipo di supporto linguistico per rappresentare gli elenchi di inizializzatori ... Ma anche se lo fosse, non sarebbe d'aiuto, perché il tuo argomento non è di tipo 'std :: initializer_list '. È solo una lista rinforzata. –

risposta

8

Quando si chiama la versione vettoriale, l'elenco di inizializzazione viene utilizzato per creare un valore temporaneo std::vector, che viene quindi passato alla funzione mediante riferimento const. Questo è possibile, perché std::vector ha un costruttore, che accetta un argomento come std::initializer_list<T>.
Tuttavia, gsl::span non ha tale costruttore e come {1,2,3} non ha un tipo, inoltre non può essere accettato dal costruttore di modelli che hai menzionato (oltre al fatto che std::initializer_list<T> non soddisfa comunque il concetto di contenitore).

One (brutto) soluzione sarebbe ovviamente quello di creare esplicitamente un array temporaneo:

func(std::array<int,3>{ 0,1,2,3 }); 

non vedo una ragione particolare, per cui gsl::span non dovrebbe avere un costruttore che prende un std::initializer_list, ma mantenere in mente che questa libreria è ancora abbastanza nuova e in fase di sviluppo attivo. Quindi forse è qualcosa che hanno trascurato, non hanno avuto il tempo di implementare, non erano sicuri di come fare correttamente o ci sono davvero alcuni dettagli, che renderebbero tale costruzione pericolosa. Probabilmente è meglio chiedere direttamente agli sviluppatori su github.


EDIT:
Come @Nicol Bolas spiega nel suo commento, questo è stato by design perché un lista di inizializzazione come {0,1,2,3} (e gli elementi all'interno) è un oggetto temporaneo e come gsl::span non è un contenitore a se stante (non assume la proprietà degli elementi), pensano che sarebbe troppo facile creare accidentalmente uno gsl::span che contenga un riferimento ciondolante a quegli elementi temporanei.

Così, mentre questo sarebbe OK:

func({ 0,1,2,3 }); 

perché la durata della lista di inizializzazione termina dopo il completamento della funzione, qualcosa di simile sarebbe creare un riferimento penzoloni:

gsl::span<const int> data{ 0,1,2,3 }; 
func(data); 
+0

@NicolBolas: Grazie, ho aggiunto questo alla mia risposta. Forse puoi dare un'occhiata, se la modifica è corretta. – MikeMB

+0

Sì, questa è l'idea di base. –

1

Span non possiede. Non possiede spazio di archiviazione. È un sostituto dell'aritmetica del puntatore, non una classe di archiviazione.

È necessario mettere i dati in una classe di archiviazione, e quindi se si vogliono fare cose intelligenti con l'aritmetica del puntatore, si fanno invece cose intelligenti con span.

Non è possibile inizializzare un intervallo con un elenco di inizializzazione, perché non c'è un posto dove inserire i dati.

Problemi correlati