Ci sono alcune opzioni a cui riesco a pensare, ciascuna con la propria bruttezza.
Un'opzione ovvia è utilizzare i puntatori (probabilmente unique_ptr
) anziché i riferimenti. Naturalmente, affinché funzioni, richiede l'allocazione dall'heap o dagli allocatori personalizzati. Penso che con un buon allocatore, questo approccio abbia dei meriti. Poi di nuovo, l'overloading dell'operatore diventerebbe semplicemente cattivo.
Un altro approccio è quello di memorizzare sottoespressioni per valore anziché per riferimento const. L'efficienza di questo approccio è molto dipendente dal compilatore, ma dal momento che si tratta fondamentalmente di un mucchio di provvisori, immagino che i compilatori moderni possano ottimizzare le copie (o almeno, molte delle copie).
L'ultimo approccio consente di mantenere la stessa struttura sul codice, ma costringe l'utente a valutare l'espressione. È necessario disporre di un solo tipo iterabile, che è il tipo sottostante dell'espressione (ad esempio, std::vector<int>
). Nessuna delle classi di espressioni deve avere i metodi begin
e end
definiti per loro, ma dovrebbe essere convertibile nel tipo sottostante. In questo modo, il codice come for(auto x : expr)
non riuscirà in fase di compilazione (poiché expr
non è iterabile), ma la scrittura di for(auto x : static_cast<vector<int>>(expr))
funziona perché l'espressione è già valutata.
Se si desidera utilizzare i cicli basati su intervalli per implementare le operazioni del modello di espressione, è possibile fornire metodi protetti o protetti da begin
e end
nelle classi del modello di espressione. Assicurati solo che ogni classe template possa accedere ai metodi begin
e end
delle altre classi template. Va bene in questo contesto poiché il modello di espressione è un parametro della funzione, quindi non dovrai preoccuparti di far ciondolare i riferimenti quando scrivi il ciclo all'interno di quella funzione.
fonte
2012-03-07 07:42:05
L''auto &&' nel ciclo 'for' basato sull'intervallo potrebbe davvero rivelarsi qualcosa da sparare facilmente nel piede - Non ho ancora capito bene quali tipi di intervallo sono esattamente interessati e perché (riferimenti lvalue a non-const: pericoloso, non-riferimento: non problematico, ???). – Philipp
@Philipp: non esiste un "tipo di intervallo". Esistono semplicemente tipi conformi al "concetto" di intervallo. Nello specifico, ci sono una coppia di override 'begin/end' che restituiscono gli iteratori di input. –
Suppongo che la risposta sia assicurarsi che i modelli di espressione non siano conformi al "concetto" di intervallo, cioè non hanno 'begin' e' end'. – Clinton