Come controllare se iteratori formano una zona di memoria contigua?
-
11-12-2019 - |
Domanda
Attualmente ho la seguente funzione per leggere un array o un vettore di dati RAW (_readStream
è un std::ifstream
):
template<typename IteratorType>
inline bool MyClass::readRawData(
const IteratorType& first,
const IteratorType& last,
typename std::iterator_traits<IteratorType>::iterator_category* = nullptr
)
{
_readStream.read(reinterpret_cast<char*>(&*first), (last-first)*sizeof(*first));
return _readStream.good();
}
.
Prima domanda: questa funzione sembra ok?
Mentre leggiamo direttamente un blocco di memoria, funzionerà solo se il blocco di memoria da first
a last
è contigua in memoria.Come controllarlo?
Soluzione
Lasciando da parte la funzione del campione, non puoi mai essere completamente sicuro che iteratori formeranno una memoria contigua senza controllare l'indirizzo di ogni elemento tra i due.
Un test di sanitàbile ragionevole, tuttavia, sarebbe semplicemente controllare se l'area di memoria tra i due è la stessa del conteggio tra i due:
assert(&*last - &*first == last - first &&
"Iterators must represent a contiguous memory region");
. Altri suggerimenti
N4183 è una cartaCiò supera l'idea di aggiungere un tratto iteratore contiguo.Attualmente è in considerazione per C ++ 1Z (si spera che C ++ 17).
Sotto di esso, è possibile eseguire std::is_contiguous_iterator<It>::value
e ottenere se It
è un iteratore contiguo o meno.(Questo richiederà il supporto dal designer dell'iteratore).
typename std::iterator_traits<IteratorType>::iterator_category* = nullptr
.
Questo è inutile perché std::iterator_traits
ha un modello primario con un tipo di membro di tipo con identità inconditonetagCodeTagCode.Si presumeva tacitamente che il parametro del modello sia un iteratore e che sia una violazione della precondizione se non è, come tale, non si ottiene SFinae ma un errore difficile se quanto sopra viene tentato con un'istanza non valida.
.Mentre leggiamo direttamente un blocco di memoria, funzionerà solo se il blocco di memoria da prima per ultimo è contiguo in memoria.Come controllarlo?
Non so quali requisiti esatti che avresti messo su un concetto di "contigua in memoria".Hai comunque considerato il seguente?
.template<typename T> bool readRawData(T* first, T* last);
Con la precondizione che
iterator_category
è un intervallo di punta-as-iteratore valido in un array.Se si desidera inserire ulteriori requisiti su
[ first, last )
(ad esempio una copiabilità banale da quando si utilizzaT
) è possibile esprimere / documentare anche quelle.