Fornire viste a un std :: container

3

Voglio mantenere un buffer di 5 secondi di dati del sensore. I dati del sensore comprendono, tra le altre cose, le letture dell'accelerometro nelle dimensioni x, y, z, le letture del giroscopio in dimensione x, y, z e il magnetometro nella dimensione x, y, z.

La mia idea iniziale è di utilizzare un std::deque<SensorReading> che memorizza 5 secondi della seguente struttura di SensorReading:

struct SensorReading {
   double time
   gyroscope g;
   accelerometer a;
   magnetometer m;
  //more substructs
} S;

Un'operazione comune sul buffer è che l'utente fornisce un tempo di inizio e di fine e vuole due iteratori che segnano la prima e l'ultima lettura del giroscopio (o magnetometro o accelerometro) entro questo intervallo di tempo dal buffer (deqeue). (A volte l'utente della lettura del giroscopio potrebbe anche essere interessato ai timestamp corrispondenti della struttura principale S.)

Nella mia mente ho l'idea di fornire una sorta di "vista" del buffer, che consente all'utente di vedere solo la sottostruttura a cui è interessato. Ma non ho un'idea chiara su come raggiungere questo obiettivo.

L'unica soluzione concettuale che ho finora è di introdurre Iteratori personalizzati alla deque, un magnetometro, un giroscopio, un acceleratore, un acceleratore e quindi esporre solo la corrispondente sottostruttura all'utente.

Non mi piace l'idea di mantenere più buffer, uno per ogni sottostruttura, perché aggiunge ridondanza al codice.

Quale sarebbe un modo per raggiungere questo obiettivo?

    
posta user695652 19.06.2015 - 16:58
fonte

1 risposta

1

È certamente fattibile, ma non è piccolo. Un esempio minimale incompleto assomiglia a:

template <typename BaseIterator, typename FieldType, FieldType SensorReading::*FieldPtr>
class FilteredIterator {
    BaseIterator base_;
    typedef FilteredIterator<BaseIterator, FieldType, FieldPtr> self_type;
public:
    // iterator type traits
    typedef FieldType value_type;
    typedef typename BaseIterator::difference_type difference_type;
    typedef typename BaseIterator::iterator_category iterator_category;
    typedef typename std::add_lvalue_reference<FieldType>::type reference_type;
    typedef typename std::add_pointer<FieldType>::type pointer_type;
    // construction and assignment
    FilteredIterator() = delete;
    explicit FilteredIterator(BaseIterator base) : base_(base) {}
    FilteredIterator(self_type const &) = default;
    FilteredIterator(self_type &&) = default;
    FilteredIterator& operator=(self_type const &) = default;
    FilteredIterator& operator=(self_type &&) = default;
    // increment/traversal
    self_type& operator++()    { ++base_; return *this; }
    self_type  operator++(int) { self_type tmp(*this); ++*this; return tmp; }
    // dereference
    reference_type operator* () { return (*base_).*FieldPtr; }
    std::add_const<reference_type> operator* () const { return (*base_).*FieldPtr; }
};

template <typename FieldType, FieldType SensorReading::*FieldPtr, typename BaseIterator>
FilteredIterator<BaseIterator, FieldType, FieldPtr> member_filter(BaseIterator iter) {
    return FilteredIterator<BaseIterator, FieldType, FieldPtr>(iter);
}

esempio di utilizzo:

std::deque<SensorReading> d;
// populate d
auto fi = member_filter<accelerometer, &SensorReading::a>(d.begin());
assert (&*fi == &(d.begin()->a));

Nota che questo omette ancora:

  • decremento e inversione iterazione
  • confronto (& lt ;, & gt ;, ==, ecc.)
  • distanza / sottrazione
  • operator->
  • ecc ...
  • corretta gestione dei membri qualificati cv, di riferimento e del puntatore

Un approccio più semplice consiste nell'utilizzare l' adattatore Boost.Iterator come punto di partenza.

    
risposta data 22.06.2015 - 14:52
fonte

Leggi altre domande sui tag