Best way to encapsulate "optional" fields within a struct generically in C++?
Asked Answered
S

4

5

I have many concrete-structs and I want to designate fields as optional (present or not-present). Just wondering what ideas people have for achieving this. Here is an example struct (fields can be other structs as well, even vectors of structs):

 struct LogonMessage_t
       {
          Header_t header; // this points to another struct containing all primitives
          std::string username;
          std::string password;
          std::vector<LogonOption_t> LogonOptions;
          int subaccountid;
          std::string Text;
       }

I'd like to default all fields to not-present and enable them one by one, perhaps in their setters. Since these structs are generated, a generic method would be preferable.

My ideas so far are:

  1. Bitmap of fields indicating if a field is set or not
  2. Use sentinel values ("\0" for std::string, -1 for int, -1.0f for float
  3. Some kind of template container/proxy encapsulating each field to indicate if it's set or not, any ideas? I think this might be the best approach.

Btw, using maps or other STL containers to encapsulate the fields won't work here, they need to be concrete structs.

Smog answered 21/3, 2011 at 14:32 Comment(0)
K
6

Sounds like you want boost.optional.

Kachine answered 21/3, 2011 at 14:38 Comment(1)
Sorry, forgot to mention that I'm not able to use boost for this particular application... I will look at its implementation to perhaps garner some ideas though!Smog
O
2

Keep it simple. Use a flag member variable that you can set by or-ing constants together and inspect by and-ing them.

Problem with sentinel values is choosing ones that are not also legal field values (now and in the future).

Oxymoron answered 21/3, 2011 at 14:39 Comment(0)
L
0

Both string and vector has an empty default state, which you can test for with if (username.empty()) etc.

For a subaccountid I would guess that 0 would be a similar empty value. Otherwise -1 could be ok.

Lifegiving answered 21/3, 2011 at 14:38 Comment(0)
V
0

I'd use one a flag. I can propose you two method, one keeping the value on the heap and one on the stack.

In the first you use a std::pair and the first field is the existence-flag. The second approach is via a boost::shard_ptr, if pointer points to 0 the field is not existing.

In both the cases my advice is not to access directly to the element in Value but using instead a couple of functions. const Value& value() const { return } Value& value() { return }

francesco

Voe answered 21/3, 2011 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.