Boost program options with default values always present when using vm.count() - c++

I've been trying to validate my passed options with boost::program_options. My command has several modes, each of which have associated params that can be specified. What I'm trying to do is ensure these associated params are passed with the mode, i.e.
unicorn --fly --magic-wings-threshold
Where --fly is the mode and --magic-wings-threshold is an associated param. What I've noticed is if --magic-wings-threshold has a default value, e.g.
("magic-wings-threshold,w", po::value<double>(&wings_thresh)->default_value(0.8, "0.8"),
"Magic wings maximum power"
)
then I can't use
if (vm.count("magic-wings-threshold")( {
// do stuff
}
to detect if the user passed that param.
It appears that default value params are always passed and detected in vm.count(). Does anyone know a workaround or alternative?

use boost::program_options::variable_value::defaulted()
if (vm["magic-wings-threshold"].defaulted()) {
// assume defaulted value
} else {
// one was provided
}

If you want to tell difference between
-k option not provided
-k provided
You should use po::value()->implicit_value(), You can tell the different situations with:
-k option not provided -> vm["k"]==0
-k option provided -> vm["k"]==1

Related

c++ best way to realise global switches/flags to control program behaviour without tying the classes to a common point

Let me elaborate on the title:
I want to implement a system that would allow me to enable/disable/modify the general behavior of my program. Here are some examples:
I could switch off and on logging
I could change if my graphing program should use floating or pixel coordinates
I could change if my calculations should be based upon some method or some other method
I could enable/disable certain aspects like maybe a extension api
I could enable/disable some basic integrated profiler (if I had one)
These are some made-up examples.
Now I want to know what the most common solution for this sort of thing is.
I could imagine this working with some sort of singelton class that gets instanced globally or in some other globally available object. Another thing that would be possible would be just constexpr or other variables floating around in a namespace, again globally.
However doing something like that, globally, feels like bad practise.
second part of the question
This might sound like I cant decide what I want, but I want a way to modify all these switches/flags or whatever they are actually called in a single location, without tying any of my classes to it. I don't know if this is possible however.
Why don't I want to do that? Well I like to make my classes somewhat reusable and I don't like tying classes together, unless its required by the DRY principle and or inheritance. I basically couldn't get rid of the flags without modifying the possible hundreds of classes that used them.
What I have tried in the past
Having it all as compiler defines. This worked reasonably well, however I didnt like that I couldnt make it so if the flag file was gone there were some sort of default settings that would make the classes themselves still operational and changeable (through these default values)
Having it as a class and instancing it globally (system class). Worked ok, however I didnt like instancing anything globally. Also same problem as above
Instancing the system class locally and passing it to the classes on construction. This was kinda cool, since I could make multiple instruction sets. However at the same time that kinda ruined the point since it would lead to things that needed to have one flag set the same to have them set differently and therefore failing to properly work together. Also passing it on every construction was a pain.
A static class. This one worked ok for the longest time, however there is still the problem when there are missing dependencies.
Summary
Basically I am looking for a way to have a single "place" where I can mess with some values (bools, floats etc.) and that will change the behaviour of all classes using them for whatever, where said values either overwrite default values or get replaced by default values if said "place" isnt defined.
If a Singleton class does not work for you , maybe using a DI container may fit in your third approach? It may help with the construction and make the code more testable.
There are some DI frameworks for c++, like https://github.com/google/fruit/wiki or https://github.com/boost-experimental/di which you can use.
If you decide to use switch/flags, pay attention for "cyclometric complexity".
If you do not change the skeleton of your algorithm but only his behaviour according to the objets in parameter, have a look at "template design pattern". This method allow you to define a generic algorithm and specify particular step for a particular situation.
Here's an approach I found useful; I don't know if it's what you're looking for, but maybe it will give you some ideas.
First, I created a BehaviorFlags.h file that declares the following function:
// Returns true iff the given feature/behavior flag was specified for us to use
bool IsBehaviorFlagEnabled(const char * flagName);
The idea being that any code in any of your classes could call this function to find out if a particular behavior should be enabled or not. For example, you might put this code at the top of your ExtensionsAPI.cpp file:
#include "BehaviorFlags.h"
static const enableExtensionAPI = IsBehaviorFlagEnabled("enable_extensions_api");
[...]
void DoTheExtensionsAPIStuff()
{
if (enableExtensionsAPI == false) return;
[... otherwise do the extensions API stuff ...]
}
Note that the IsBehaviorFlagEnabled() call is only executed once at program startup, for best run-time efficiency; but you also have the option of calling IsBehaviorFlagEnabled() on every call to DoTheExtensionsAPIStuff(), if run-time efficiency is less important that being able to change your program's behavior without having to restart your program.
As far as how the IsBehaviorFlagEnabled() function itself is implemented, it looks something like this (simplified version for demonstration purposes):
bool IsBehaviorFlagEnabled(const char * fileName)
{
// Note: a real implementation would find the user's home directory
// using the proper API and not just rely on ~ to expand to the home-dir path
std::string filePath = "~/MyProgram_Settings/";
filePath += fileName;
FILE * fpIn = fopen(filePath.c_str(), "r"); // i.e. does the file exist?
bool ret = (fpIn != NULL);
fclose(fpIn);
return ret;
}
The idea being that if you want to change your program's behavior, you can do so by creating a file (or folder) in the ~/MyProgram_Settings directory with the appropriate name. E.g. if you want to enable your Extensions API, you could just do a
touch ~/MyProgram_Settings/enable_extensions_api
... and then re-start your program, and now IsBehaviorFlagEnabled("enable_extensions_api") returns true and so your Extensions API is enabled.
The benefits I see of doing it this way (as opposed to parsing a .ini file at startup or something like that) are:
There's no need to modify any "central header file" or "registry file" every time you add a new behavior-flag.
You don't have to put a ParseINIFile() function at the top of main() in order for your flags-functionality to work correctly.
You don't have to use a text editor or memorize a .ini syntax to change the program's behavior
In a pinch (e.g. no shell access) you can create/remove settings simply using the "New Folder" and "Delete" functionality of the desktop's window manager.
The settings are persistent across runs of the program (i.e. no need to specify the same command line arguments every time)
The settings are persistent across reboots of the computer
The flags can be easily modified by a script (via e.g. touch ~/MyProgram_Settings/blah or rm -f ~/MyProgram_Settings/blah) -- much easier than getting a shell script to correctly modify a .ini file
If you have code in multiple different .cpp files that needs to be controlled by the same flag-file, you can just call IsBehaviorFlagEnabled("that_file") from each of them; no need to have every call site refer to the same global boolean variable if you don't want them to.
Extra credit: If you're using a bug-tracker and therefore have bug/feature ticket numbers assigned to various issues, you can creep the elegance a little bit further by also adding a class like this one:
/** This class encapsulates a feature that can be selectively disabled/enabled by putting an
* "enable_behavior_xxxx" or "disable_behavior_xxxx" file into the ~/MyProgram_Settings folder.
*/
class ConditionalBehavior
{
public:
/** Constructor.
* #param bugNumber Bug-Tracker ID number associated with this bug/feature.
* #param defaultState If true, this beheavior will be enabled by default (i.e. if no corresponding
* file exists in ~/MyProgram_Settings). If false, it will be disabled by default.
* #param switchAtVersion If specified, this feature's default-enabled state will be inverted if
* GetMyProgramVersion() returns any version number greater than this.
*/
ConditionalBehavior(int bugNumber, bool defaultState, int switchAtVersion = -1)
{
if ((switchAtVersion >= 0)&&(GetMyProgramVersion() >= switchAtVersion)) _enabled = !_enabled;
std::string fn = defaultState ? "disable" : "enable";
fn += "_behavior_";
fn += to_string(bugNumber);
if ((IsBehaviorFlagEnabled(fn))
||(IsBehaviorFlagEnabled("enable_everything")))
{
_enabled = !_enabled;
printf("Note: %s Behavior #%i\n", _enabled?"Enabling":"Disabling", bugNumber);
}
}
/** Returns true iff this feature should be enabled. */
bool IsEnabled() const {return _enabled;}
private:
bool _enabled;
};
Then, in your ExtensionsAPI.cpp file, you might have something like this:
// Extensions API feature is tracker #4321; disabled by default for now
// but you can try it out via "touch ~/MyProgram_Settings/enable_feature_4321"
static const ConditionalBehavior _feature4321(4321, false);
// Also tracker #4222 is now enabled-by-default, but you can disable
// it manually via "touch ~/MyProgram_Settings/disable_feature_4222"
static const ConditionalBehavior _feature4222(4222, true);
[...]
void DoTheExtensionsAPIStuff()
{
if (_feature4321.IsEnabled() == false) return;
[... otherwise do the extensions API stuff ...]
}
... or if you know that you are planning to make your Extensions API enabled-by-default starting with version 4500 of your program, you can set it so that Extensions API will be enabled-by-default only if GetMyProgramVersion() returns 4500 or greater:
static ConditionalBehavior _feature4321(4321, false, 4500);
[...]
... also, if you wanted to get more elaborate, the API could be extended so that IsBehaviorFlagEnabled() can optionally return a string to the caller containing the contents of the file it found (if any), so that you could do shell commands like:
echo "opengl" > ~/MyProgram_Settings/graphics_renderer
... to tell your program to use OpenGL for its 3D graphics, or etc:
// In Renderer.cpp
std::string rendererType;
if (IsDebugFlagEnabled("graphics_renderer", &rendererType))
{
printf("The user wants me to use [%s] for rendering 3D graphics!\n", rendererType.c_str());
}
else printf("The user didn't specify what renderer to use.\n");

How to create option aliases with boost::program_options?

I would like to be able to have the possibility to create option aliases with boost::program_options that stores their arguments under the same key/label.
The architecture of my software uses different specialized option parsers depending on the value argv[1]. However some options are shared, like my option --inputs.
inputOptions.add_options()
("--inputs",
po::value< std::vector<std::string> >()->value_name("paths"),
"List of files to edit.\n");
For compatibility with older version of the program, I would like to add to one of the sub-parsers a compatibility option --input that stores its argument(s) under "--inputs". Ideally that option should take at most one argument instead of arbitrarily many. However if you provide a solution that makes --input identical to --inputs, I guess it's fine too, as in this case positional options are sent to "--inputs" anyway.
Thank you for any help !
You can use extra_parser(see Non-conventional syntax in the docs), i.e. parser that can be used to manipulates tokens from input before they are processed further. It can be used for things like translating --run into --command=run etc.
Extra parser is a functor that has the following signature:
std::pair<std::string, std::string>(const std::string &s)
It should return option name in pair::first and (optional) option value in pair::second. Empty pair::first means that the extra parser has not parsed anything. Value (i.e. pair::second) can be empty - only option name has been parsed. If returned pair is valid then the name or name/value pair is used instead of parsing the original token via normal machinery.
First, we write aliasing function:
using OptionAliases = std::map<std::string, std::string>;
std::pair<std::string, std::string>
renameOptions(const std::string &token, const OptionAliases &aliases)
{
auto rtoken(boost::make_iterator_range(token));
// consume "--" prefix
if (!boost::algorithm::starts_with(rtoken, "--")) { return { "", "" }; }
rtoken.advance_begin(2);
// find equal sign (returns iterator range)
const auto eq(boost::algorithm::find_first(rtoken, "="));
// extract option (between "--prefix" and "="/end()) and map it to output
const auto faliases(aliases.find(std::string(rtoken.begin(), eq.begin())));
if (faliases == aliases.end()) { return { "", "" }; }
// return remapped option and (optionally) value after "="
return std::make_pair(faliases->second
, std::string(eq.end(), rtoken.end()));
}
It simply splits input token into --, name, =, value (no value if there is no = sign) and if the name is found in the provided alias mapping it returns (remapped-name, value).
Then, we create the parser itself, using lambda:
boost::program_options::ext_parser optionAlias(OptionAliases &&aliases)
{
return [aliases{std::move(aliases)}](const std::string &token)
{
return renameOptions(token, aliases);
};
}
(Needs at least C++14, for C++11 change to return [aliases](con...)
You can plug this parser into cmdline parser:
parser.extra_parser(optionAlias({{"mark.twain", "samuel.clemens"}
, {"lewis.caroll", "charles.dodgson"}}));
Now, in the example above, both --mark.twain and --samuel.clemens will point to vars["samuel.clemens"] and both --lewis.caroll and --charles.dodgson will point to vars["charles.dodgson"].
Caveats:
Works only for command line parser.
Expects allow_long style (long options with -- prefix). Can be changed in the code.
Expects long_allow_adjacent style (values allowed in one token using =). Can be changed in the code, as well.
If there is any non-option token that parses as --alias then it is translated as well since there is no context. No way to circumvent.
Example: If there's an option with name name that expects value and long_allow_next style is used, then --name=--mark.twain will be parsed as option name with value --mark.twain (as expected) while --name --mark.twain will be parsed as option name with value samuel.clemens.
Short of that, it works as expected.
Hope it helps.
Have you tried using the form po::value<...>(&variable)? The value of the option is saved directly to the variable after parsed. You can then add two options --input and --inputs pointing to the same variable. Additionally, you'd probably have to check that only one of the two options is used and, otherwise, show an error message.
I hope I've understood your question correctly.
By default boost::program_options allows the prefix of a long option to match that option. So the code you have written will already accept --input as an alias for --inputs.

Changing model parameters by cPar in other module

I am using this module hierarchy :
Node: {udpApp[0]<->udp<->networkLayer->wlan[0]} and wlan[0]: {CNPCBeacon<->mac<->radio}
I have given some initial parameter in the ini file for udpApp as :
**.host*.numUdpApps = 2
**.host*.udpApp[0].typename = "UDPBasicApp"
**.host*.udpApp[0].chooseDestAddrMode = "perBurst"
**.host*.udpApp[0].destAddresses = "gw1"
**.host*.udpApp[0].startTime = 1.32s
**.host*.udpApp[0].stopTime = 1.48s
But at run time I want to change the startTime and stopTime for udpAPP[0] through CNPCBeacon module. Hence I changed CNPCBeacon.cc as:-
cModule* parentmod = getParentModule();
cModule* grantParentmod = parentmod->getParentModule();
cModule* udpmod;
for (cSubModIterator iter(*grantParentmod); !iter.end(); iter++)
{
//EV<<"get the modulde "<< iter()->getFullName()<<endl;
if (strcmp(iter()->getFullName(), "udpApp[0]") == 0)
{
udpmod = iter();
break;
}
}
cPar& startTime = udpmod->par("startTime");
cPar& stopTime = udpmod->par("stopTime");
And I am successfully able to receive the values of startTime and stopTime. However I want to change these value in current module, which is resulting in an error by following code:
udpmod->par("startTime").setDoubleValue(4.2);
Can anybody please suggest me a way to change it at run time.
Declaring your parameter as volatile should solve your problem. But for future reference I'll provide further explanation below
Volatile vs. non-volatile:
Here it depends how you want to use this parameter. Mainly via the .ini file you have two types of parameters: volatile and non-volatile.
volatile parameters are read every time during your run. That woule be helpful if you want this parameter to be generated by a built-in function, for example, uniform(0,10) each time this volatile parameter will get a different value.
On the other hand non-volatile parameters are read just one, as they don't change from run to run.
Using the volatile type parameter does not give you full flexibility, in the sense that your parameter value will always fall with in a range predefined in the .ini
Dynamic Variable (parameter) Reassignment:
Instead what you could do is use a more robust approach, and re-define the variable which stores the value from that module parameter each time you have to do so.
For example in your case you could do the following:
varHoldingStartTime = par("startTime").doubleValue();
varHoldingStartTime = 4.2;
This way the actual value will change internally without reflecting to your run.
Parameter Studies:
Alternatively if you want this change of the parameter to be applied to multiple runs you could use the advanced built-in approach provided by OMNeT++ which allows you to perform Parameter Studies.
I have explained here how Parameter Studies work: https://stackoverflow.com/a/30572095/4786271 and also here how it can be achieved with constraints etc: https://stackoverflow.com/a/29622426/4786271
If none of the approaches suggested by me fit your case, answers to this question altogether might solve your problem: How to change configuration of network during simulation in OMNeT++?
EDIT: extending the answer to roughly explain handleParameterChange()
I have not used handleParameterChange() before as well, but from what can I see this function provides a watchdog functionality to the module which utilizes it.
To activate this functionality first the void handleParameterChange(const char *parameterName); has to be re-defined.
In essence what it seems to do is the following:
Assume we have two modules moduleA and moduleB and moduleB has parameter parB. moduleA changes the parB and when that happens, moduleB reacts to this change based on the behaviour defined in:
moduleB::handleParameterChange(parB);
The behaviour could be re-reading the original value for parB from the .ini etc.

Integrating LLVM passes

This maybe a rookie question but is there a way to integrate my LLVM modulepass to be called by default during the transformation phase?
Right now I am using this syntax to load my pass and register it
~/llvm/llvm/build/Debug+Asserts/bin/clang -Xclang -load -Xclang ~/llvm/llvm/build/Debug+Asserts/lib/SOMEPASSLIB.so
(The problem is when I want to build some package with this pass, the compiler accepts it when I say, pass the loading part as CFLAGS env variable, but some makefiles use CFLAGS for linking too, and the linker has no idea what it can do with this information and fails the build :\ )
There are couple of files you need to modify in order to define your pass inside LLVM core:
i) inside your pass: loadable pass is registered like this (assuming your pass name is FunctionInfo):
char FunctionInfo::ID = 0;
RegisterPass<FunctionInfo> X("function-info", "Functions Information");
you need to change it to be like this:
char FunctionInfo::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionInfo, "function-info", "Gathering Function info", false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTree)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
.... // initialize all passes which your pass needs
INITIALIZE_PASS_END(FunctionInfo, "function-info", "gathering function info", false, false)
ModulePass *llvm::createFunctionInfoPass() { return new FunctionInfo(); }
ii) you need to register your pass inside llvm as well, at least in InitializePasses.h and LinkAllPasses.h.
in LinkAllPasses.h you should add :
(void)llvm::createFunctionInfoPass();
and in InitializePasses.h add :
void initializeFunctionInfoPass(PassRegistry &);
iii) beside this modifications you might need to change another file depend on where you are going to add your pass. for instance if you are going to add it in lib/Analysis/ you also need to add one line to Analysis.cpp as below :
initializeFunctionInfoPass(Registry);
or if you are going to add it as new Scalar Transform you need to modify both Scalar.h and Scalar.cpp likewise.

ADO Command saying that I am inserting NULL, when I'm not

I'm using ADO to communicate with my Sybase server..
This is how I'm executing a simple command:
_ConnectionPtr m_ConnPtr;
//... Instantiate connection
_CommandPtr m_CommPtr;
m_CommPtr->CreateInstance(__uuidof(Command))
m_CommPtr->ActiveConnection = m_ConnPtr;
Variant m_variant;
m_variant.SetString("My Param Value");
_ParameterPtr ParamPtr;
ParamPtr = m_CommPtr->CreateParameter("#StrParam", (DataTypeEnum) m_variant.vt, adParamInput, NULL, m_variant);
m_CommPtr->Parameters->Append(PrmPtr);
m_CommPtr->CommandText = "EXECUTE my_stored_procedure #StrParam";
m_CommPtr->Execute(NULL, NULL, adOptionUnspecified);
#StrParam is supposed to be a VarChar type..
Running this gives me an error:
Attempt to insert NULL value into column 'StrParam'. table 'MYTABLE';
column does not allow nulls. Update fails.
I'm not sure why I'm getting this error, since I am specifiying its value ("My Param Value")..
Does anyone know what I'm doing wrong?
(I didn't include the Stored procedure,, because I'm sure there's nothing wrong with the procedure itself.. Other application using the same procedure works fine. So there must be something wrong with how I'm using the parametized command)
I have no clue what your Variant class even is. But the traditional variant type (vt) and the ADO data type are not synonymous. Second, you're not setting up the call nor parameters correctly for a typical stored-proc invoke.
Below is how you would do this using a standard stored proc call and variant_t from the comutil library:
_CommandPtr m_CommPtr(__uuidof(Command));
m_CommPtr->ActiveConnection = m_ConnPtr;
m_CommPtr->CommandType = adoCmdStoredProc;
m_CommPtr->CommandText = L"my_stored_procedure";
// setup parameter
variant_t vParam = L"My Param Value";
_ParameterPtr ParamPtr = m_CommPtr->CreateParameter(L"#StrParam", adBSTR, adParamInput, 0, vParam);
m_CommPtr->Parameters->Append(ParamPtr);
m_CommPtr->Execute(NULL, NULL, adOptionUnspecified);
Note that the ParamPtr is generally optional and you can straight-away append the parameter to the command's Parameters collection if you don't need it for anything else, like this:
m_CommPtr->Parameters->Append(m_CommPtr->CreateParameter(
L"#StrParam", adBSTR, adParamInput, 0, vParam));
The method you're using is common for parameters that are both input and output, as you retain the parameter object reference to extract the output side of the parameter. I see no evidence of that in your call, which is the only reason I mention it here.
Also note that unless the command returns rows for a result set you should also invoke with adExecuteNoRecords for the execution third option (which is typical for many fire-and-forget stored procedure executions)
Finally, the names of the parameters are not important unless you use the NamedParameters property of the command object. This is commonly done when you have additional parameters with default values that you would like to retain, setting only specific parameters as part of your append list.
Best of luck.