Arne
Arne

Reputation: 1151

Derive from std:string to add typedefs and enums

For UDP packages exchanged between client and server I would like to support two kinds of string fields:

To self-document the layout of our packages I would like to use simple struct declarations:

struct ABC {
  vstring a;
  cstring b;
}

And call overloaded functions get(char*, vstring& v) and get(char*, cstring&) inside de/serialization function like this:

void deserialize(const char* bytes, ABC& msg) {
  get(msg.a);
  get(msg.b);
}

void serialize(char* bytes, const ABC& msg) {
  put(msg.a);
  put(msg.b);
}

However, for the user vstring and cstring should ideally behave just like normal std::string.

My first idea was to simply make std::string a public base of vstring and cstring such that the two classes can be disriminated during overload-resolution but behave the same for the user. But since deriving from std::string is discouraged, I am unsure what to do.

Upvotes: 5

Views: 247

Answers (3)

Tony Delroy
Tony Delroy

Reputation: 106096

The danger of deriving from std::string is that the destructor is not virtual, so someone might do this:

std::string* p = new vstring;
delete p;

You'd have undefined behaviour. If you think that code like that has no chance of being written in your environment/system, knock yourself out and derive from std::string.

Guidelines:

  • If the vstring and cstring classes are only being used in a very limited, controlled environment - preferably by one or a small number of developers with whom you can communicated the expected - and monitor the actual - usage, or where it's clear that dynamic allocation and polymorphism won't be abused to handle them, all's good.

  • At the other extreme - if they're in your interfaces to unspecified amounts of uncontrolled code, where it's not even practical to inform all the would-be client developers of the issue - that's not good, and a scenario in which you should prefer not to derive from types without virtual destructors.


That said, do you really need to encode the serialisation style in the type? They have to write serialisation and deserialisation routines anyway, which list the fields to be serialised, and they could specify the format (NUL-terminated vs. length-prefixed or whatever else) in there too.

Upvotes: 4

Anton Savin
Anton Savin

Reputation: 41301

Ideologically, the way of serialization shouldn't affect the type of data, so I'd better do something like this:

void serializeNullTerminated(char* bytes, const std::string& msg);
void deserializeNullTerminated(const char* bytes, std::string& msg);

void serializeWithSize(char* bytes, const std::string& msg);
void deserializeWithSize(const char* bytes, std::string& msg);

Or pass an additional parameter to the functions:

void serialize(SerializationType st, char* bytes, const std::string& msg);
void deserialize(SerializationType st, const char* bytes, std::string& msg);

Or you can make them template:

template<SerializationType st>
void serialize(char* bytes, const std::string& msg);
template<SerializationType st>
void deserialize(const char* bytes, std::string& msg);

The point is, the user won't have to deal with different types of strings, in their code, they only have to choose the way of serialization/deserialization.

Upvotes: 2

bolov
bolov

Reputation: 75697

You have to decouple the computation from the messages. So in your program you work with std::string, and when you need to send/receive strings you pass messages conform with your protocol.

So the only public interfaces of your library/application/whatever should be something like:

int send_message(std::string const &s, int mode, ... destination ... etc);
int receive_message(std::string &s, int mode, ... source ... etc);

(with possible overloads of char *c (null-terminated) for s).

with mode being a flag MODE_CSTRING or MODE_VSTRING.

Internally you send/receive:

  • a vector of null-terminated characters or
  • the size and then the vector of characters.

You don't even need to create classes for cstring and vstring.

Upvotes: 1

Related Questions