2

I have a program that I run repeatedly with various parameter sets. Different parameters are used in different parts of the program (including different source files). The same parameter may also be used in different places. However, all parameters are constant during run-time after they have been set.

I discovered very quickly that declaring the parameters locally does not make sense (it involves having to remember where every parameter is defined, etc.), so I resorted to using a params.h where I declared and defined all the parameters: const int Param1 = 42;, etc.

The downside of this is that I have to recompile every time I change a parameter. So I'm thinking of using the method below. It relies on usingvolatile and const_cast, which is normally considered "dirty", but it ensures once the parameters have been set in main, they are not accidentally changed anywhere else in the program.

I'm wondering whether people think this is OK, because eventually I want to open-source my code.

In params.h:

namespace Params
{
extern volatile const int Param1;
// etc.
}

In main.cpp:

#include "params.h"

volatile const int Params::Param1 = 0;

int main(int argc, char* argv[])
{
    int* const pParam1 = const_cast<int*>(Params::Param1);
    *pParam1 = // Get value from argv[] or some config.ini file.
    // etc.
}
  • 1
    Don't use volatile. It means something else entirely. – david.pfx Jun 24 '14 at 4:01
3

Don't use volatile const, it sounds like nonsense! Instead, use a class/struct and initialize all variables in the constructor. You can still use const.

Params.h:

struct ConfigParams {

    const int param1;
    const int param2;
    // ...

    // Define a constructor that will load stuff from a configuration file.
    // Tune this to meet your needs, such as parsing the data from a startup command line.
    ConfigParams(const std::string & configFileName);
};

// The global that you will use to fetch the configurations during runtime.
extern const ConfigParams configParams;

Params.cpp:

// Declare the global configuration data table:
const ConfigParams configParams("app_configs.ini");

// The constructor:
ConfigParams::ConfigParams(const std::string & configFileName)
    : param1(getConfigFromFile(configFileName, "param1"))
    , param2(getConfigFromFile(configFileName, "param2"))
    // and so on ...
{
}

// And this function would open the file and lookup the requested parameter key, returning its value:
int getConfigFromFile(const std::string & configFileName, const std::string & key)
{
    // TODO...
}
  • 1
    Spot on, just what I wanted. I knew there must be a better way than my hack. A bit embarrassed I didn't come up with it myself. – MGA Jun 24 '14 at 15:07
  • @MGA I feel exactly the same! – Nikos Oct 20 '18 at 6:18
1

You should read your parameters from a configuration file when the program starts. You can pass the file name on the command line. See this answer for information on using boost::property_tree to read a parameter file.

0

It is not only unreasonable, it is forbidden by the standard to modify a const variable.

[dcl.type.cv]/4 tells (emphasize mine) :

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

The idea is still good. Declare a variable extern, and define it in a source file. When you need to change it, you don't have files to recompile.

If you don't want to recompile, you have several options :

  • load parameters from a file
  • read environment variable
  • pass as parameter to the program

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.