Suppose I am developing a class which implements some high-level application logic. I want the “configuration”/”attributes” of this logic to be modifiable at run-time (with some default values). Some attributes may be read-only, others may be read-write.

I am going to use a custom “networking” layer as an example:

class Network
{
public:
   void setConfigValueA(TypeA value);
   TypeA configValueA() const;

   void setConfigValueB(TypeB value);
   TypeB configValueB() const;

   //...
};

The way I have shown the code is to introduce a “getter” and “setter” method for each configuration attribute.

Examples for the network layer might be timeout values, error counters, modes, addresses, etc…

However, I am concerned that, if I have more than a handful of attributes, this technique becomes unwieldy. Or rather, it make the interface complex.

Another option I thought of is:

class Network
{
public:
   void setAttribute(AttributeID id, Variant value);
   Variant attribute(AttributeID id) const;
};

This doesn’t make the underlying logic any less complicated (in fact, it probably makes it much more complex), but it does clean up the interface. It also allows me to add new attributes without modifying the interface. Some of the complexity here is converting the specific types into something generic that can fit in my Variant type. There also needs to be logic to set the appropriate value based upon the AttributeID.

To my knowledge, the latter option is similar to what ioctrl in POSIX achieves. A generic (unchanging) interface used to modify specific attributes of an underlying piece of code (e.g., a driver).

I am wondering, what other options are there to achieve this run-time attribute/configuration setting? Are there some examples/resources you could point me to?

There’s no need to constrain yourself to integer IDs.
Offer an interface that looks like
a HashMap from strings to strings.
Then it resembles the .yaml config
file that your users are probably
already accustomed to editing.

Case smash the keys to lower,
so it’s hard for caller to
mis-specify a key’s spelling.

1

The collected set of attributes of your configuration is nothing but a bunch of data which needs to be modeled like any other kind of data: by creating some data model or data schema for it. If you prefer DDD terms, you can also think of a Domain model, for the bounded context of the configuration of a certain domain aspect.

How this model has to look like depends ultimately on the specific attributes,

  • their semantics and relationships,

  • their commonalaties and dependencies among each other

  • how uniform they are

  • how flexible and extendible you need the model to be.

You design this the same way as you design a data model or object model for business data, applying all what you may have learned in the past about relational modeling, hierarchical modeling, OO modeling or Domain Driven Design, and how such a model expresses itself in C++.

In short: there is no secret, special method for handling many runtime configuration parameters. The kind of model you need for configuration data is not different from a data / object model for any other kind of business data, and the techniques for creating such models are the same.