0

I need to read some data from a binary file, this file contains some data frames with a different size, depending on the version. For example:

version 1 has a frame of 32 floats, version 2 has a frame of 48, etc...

I store in the header the file version, my question is:

I have these structures:

struct ReplayFrame_8
{
    float data[116];
    ReplayFrame_8();
};


struct ReplayFrame 
{
    double time;
    float data[212];
    ReplayFrame();
};

when I load the replay I put the frames in a buffer, but the buffer is a vector of my frames std::vector<ReplayFrame> frames;

Obviously this doesn't work, 'cause when I do the push_back, if is not ReplayFrame gives me the error..

How can I solve this??

ghiboz
  • 7,863
  • 21
  • 85
  • 131

1 Answers1

2

One possible option:

struct BaseReplayFrame {
  int frame_type;

  BaseReplayFrame(int ft ) {
    frame_type = ft;
  }
};

struct ReplayFrame_8 : public BaseReplayFrame {
  float data[116];
  ReplayFrame_8() : BaseReplyFrame(8) {
    //...
  }
};

struct ReplayFrame : public BaseReplayFrame {
  double time;
  float data[212];
  ReplayFrame():BaseReplayFrame(0): {
  }
};

Then, you can declare your vector as

std::vector<unique_ptr<BaseReplayFrame>> frames;

and insert there frames created via new, something like

frames.push_back(new ReplayFrame_8());

(see Why can I not push_back a unique_ptr into a vector? for details on pushing unique_ptr's into vectors, but here it doesn't seem to be necessary).

If you don't want to have frame_type within your BaseReplayFrame - it should be also possible via having vector element type as something like

pair<int,unique_ptr<BaseReplayFrame>>

, though it will be probably more cumbersome.

EDIT: a better option if having non-empty BaseReplayFrame is ok:

struct BaseReplayFrame {
  virtual float* get_data() = 0;
  virtual size_t get_data_size() = 0;
};

struct ReplayFrame_8 : public BaseReplayFrame {
  float data[116];
  virtual float* get_data() { return data; }
  virtual size_t get_data_size() { return 116; }
};

struct ReplayFrame : public BaseReplayFrame {
  double time;
  float data[212];
  virtual float* get_data() { return data; }
  virtual size_t get_data_size() { return 212; }
};

frames is declared as above, and data can be accessed without cast, via

size_t datasz = frames[i]->get_data_size();
float* data = frames[i]->get_data();

Access to time can be added in a similar manner.

Community
  • 1
  • 1
No-Bugs Hare
  • 1,557
  • 14
  • 15
  • Why are you `std::move`-ing the `new` expression ? – Telokis Jun 04 '15 at 16:02
  • thanks, but for the float array? if is not in the base is not stored – ghiboz Jun 04 '15 at 18:09
  • It is stored, it is just that you should either cast it to correct pointer based on frame_type, or to add virtual get_data() = 0; to BaseReplyFrame, and override it in each of derived ReplyFrame classes as virtual get_data() { return data; } – No-Bugs Hare Jun 04 '15 at 18:50
  • thanks @No-BugsHare , so if I push as base type and when I use I cast as derived type it works? I try! :) – ghiboz Jun 04 '15 at 22:08
  • You create it as a derived type (on heap), store as a pointer to base type, and use it as a pointer to derived type. It works as storing and casting pointer doesn't change the pointed-to type. – No-Bugs Hare Jun 05 '15 at 05:07