mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-13 16:46:47 +00:00
add a signal/slot mechanism. 2 APIs : one generic version, and one string API (commented)
This commit is contained in:
parent
5e5ddd5b7b
commit
9ceab6099c
133
fairmq/options/FairMQEventManager.h
Normal file
133
fairmq/options/FairMQEventManager.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence version 3 (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* File: FairMQEventManager.h
|
||||
* Author: winckler
|
||||
*
|
||||
* Created on August 12, 2016, 13:50 PM
|
||||
*/
|
||||
|
||||
#ifndef FAIRMQEVENTMANAGER_H
|
||||
#define FAIRMQEVENTMANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
enum class EventId : uint32_t
|
||||
{
|
||||
// Place your new EventManager events here
|
||||
UpdateParam = 0,
|
||||
Custom = 1,
|
||||
|
||||
};
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
template <EventId,typename ...Args> struct Traits;
|
||||
template <typename T> struct Traits<EventId::UpdateParam, T> { using signal_type = boost::signals2::signal<void(const std::string&, T)>; } ;
|
||||
template <typename T> struct Traits<EventId::UpdateParam, std::vector<T> > { using signal_type = boost::signals2::signal<void(const std::string&, const std::vector<T>& )>; } ;
|
||||
|
||||
|
||||
template <> struct Traits<EventId::UpdateParam, std::string> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
|
||||
|
||||
template<std::size_t N> struct Traits<EventId::UpdateParam, const char[N]> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
|
||||
|
||||
template <typename ...T> struct Traits<EventId::Custom,T...> { using signal_type = boost::signals2::signal<void(T...)>; } ;
|
||||
|
||||
/*
|
||||
template <EventId, typename ...Args> struct Traits2;
|
||||
template <> struct Traits2<EventId::UpdateParam> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
|
||||
template <typename ...T> struct Traits2<EventId::UpdateParam,T...> { using signal_type = boost::signals2::signal<void(const std::string&, T...)>; } ;
|
||||
template <> struct Traits2<EventId::UpdateParamInt> { using signal_type = boost::signals2::signal<void(const std::string&, int)>; } ;
|
||||
// */
|
||||
}
|
||||
|
||||
|
||||
class FairMQEventManager
|
||||
{
|
||||
public:
|
||||
typedef std::pair<EventId,std::string> EventKey;
|
||||
|
||||
FairMQEventManager() : fEventMap() {}
|
||||
virtual ~FairMQEventManager(){}
|
||||
|
||||
|
||||
template <EventId event, typename... ValueType, typename F>
|
||||
void Connect(const std::string& key, F&& func)
|
||||
{
|
||||
GetSlot<event,ValueType...>(key).connect(std::forward<F>(func));
|
||||
}
|
||||
|
||||
template <EventId event, typename... ValueType>
|
||||
void Disonnect(const std::string& key)
|
||||
{
|
||||
GetSlot<event,ValueType...>(key).disconnect();
|
||||
}
|
||||
|
||||
|
||||
template <EventId event, typename... ValueType, typename... Args>
|
||||
void Emit(const std::string& key, Args&&... args)
|
||||
{
|
||||
GetSlot<event,ValueType...>(key)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
template <EventId event>
|
||||
bool EventKeyFound(const std::string& key)
|
||||
{
|
||||
if (fEventMap.find(std::pair<EventId,std::string>(event,key) ) != fEventMap.end())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
std::map<EventKey, boost::any> fEventMap;
|
||||
|
||||
|
||||
template <EventId event, typename... T, typename Slot = typename Events::Traits<event,T...>::signal_type,
|
||||
typename SlotPtr = boost::shared_ptr<Slot> >
|
||||
Slot& GetSlot(const std::string& key)
|
||||
{
|
||||
try
|
||||
{
|
||||
EventKey eventKey = std::make_pair(event,key);
|
||||
//static_assert(std::is_same<decltype(boost::make_shared<Slot>()),SlotPtr>::value, "");
|
||||
if (fEventMap.find(eventKey) == fEventMap.end())
|
||||
fEventMap.emplace(eventKey, boost::make_shared<Slot>());
|
||||
|
||||
return *boost::any_cast<SlotPtr>(fEventMap.at(eventKey));
|
||||
// auto &&tmp = boost::any_cast<SlotPtr>(fEventMap.at(eventKey));
|
||||
// return *tmp;
|
||||
}
|
||||
catch (boost::bad_any_cast const &e)
|
||||
{
|
||||
LOG(ERROR) << "Caught instance of boost::bad_any_cast: "
|
||||
<< e.what() << " on event #" << static_cast<uint32_t>(event) << " and key" << key;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* FAIRMQEVENTMANAGER_H */
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
using namespace std;
|
||||
|
||||
FairMQProgOptions::FairMQProgOptions()
|
||||
: FairProgOptions()
|
||||
: FairProgOptions(), FairMQEventManager()
|
||||
, fMQParserOptions("MQ-Device parser options")
|
||||
, fMQOptionsInCfg("MQ-Device options")
|
||||
, fMQOptionsInCmd("MQ-Device options")
|
||||
|
@ -26,6 +26,7 @@ FairMQProgOptions::FairMQProgOptions()
|
|||
, fHelpTitle("***** FAIRMQ Program Options ***** ")
|
||||
, fVersion("Beta version 0.1")
|
||||
, fMQKeyMap()
|
||||
// , fSignalMap() //string API
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -43,10 +44,10 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
|
|||
// init description
|
||||
InitOptionDescription();
|
||||
// parse command line options
|
||||
if (ParseCmdLine(argc, argv, fCmdLineOptions, fVarMap, allowUnregistered))
|
||||
if (FairProgOptions::ParseCmdLine(argc, argv, fCmdLineOptions, fVarMap, allowUnregistered))
|
||||
{
|
||||
LOG(ERROR) << "Could not parse cmd options";
|
||||
exit(EXIT_FAILURE);
|
||||
// ParseCmdLine return 0 if help or version cmd not called. return 1 if called
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
// if txt/INI configuration file enabled then parse it as well
|
||||
|
@ -55,8 +56,9 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
|
|||
// check if file exist
|
||||
if (fs::exists(fConfigFile))
|
||||
{
|
||||
if (ParseCfgFile(fConfigFile.string(), fConfigFileOptions, fVarMap, allowUnregistered))
|
||||
if (FairProgOptions::ParseCfgFile(fConfigFile.string(), fConfigFileOptions, fVarMap, allowUnregistered))
|
||||
{
|
||||
// ParseCfgFile return -1 if cannot open or read config file. It return 0 otherwise
|
||||
LOG(ERROR) << "Could not parse config";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -86,7 +88,7 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
|
|||
set_global_log_level(log_op::operation::GREATER_EQ_THAN, fSeverityMap.at("DEBUG"));
|
||||
}
|
||||
|
||||
PrintOptions();
|
||||
|
||||
|
||||
// check if one of required MQ config option is there
|
||||
auto parserOption_shptr = fMQParserOptions.options();
|
||||
|
@ -115,6 +117,7 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
|
|||
}
|
||||
else
|
||||
{
|
||||
// if cmdline mq-config called then use the default xml/json parser
|
||||
if (fVarMap.count("mq-config"))
|
||||
{
|
||||
LOG(DEBUG) << "mq-config: Using default XML/JSON parser";
|
||||
|
@ -177,6 +180,7 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
|
|||
UserParser<FairMQParser::XML>(ss, id);
|
||||
}
|
||||
}
|
||||
FairProgOptions::PrintOptions();
|
||||
}
|
||||
|
||||
|
||||
|
@ -206,7 +210,6 @@ int FairMQProgOptions::UpdateChannelMap(const FairMQMap& channels)
|
|||
// create key for variable map as follow : channelName.index.memberName
|
||||
void FairMQProgOptions::UpdateMQValues()
|
||||
{
|
||||
|
||||
for(const auto& p : fFairMQMap)
|
||||
{
|
||||
int index = 0;
|
||||
|
@ -232,8 +235,15 @@ void FairMQProgOptions::UpdateMQValues()
|
|||
UpdateVarMap<std::string>(methodKey,channel.GetMethod());
|
||||
UpdateVarMap<std::string>(addressKey,channel.GetAddress());
|
||||
UpdateVarMap<std::string>(propertyKey,channel.GetProperty());
|
||||
|
||||
|
||||
//UpdateVarMap<std::string>(sndBufSizeKey, std::to_string(channel.GetSndBufSize()));// string API
|
||||
UpdateVarMap<int>(sndBufSizeKey,channel.GetSndBufSize());
|
||||
|
||||
//UpdateVarMap<std::string>(rcvBufSizeKey, std::to_string(channel.GetRcvBufSize()));// string API
|
||||
UpdateVarMap<int>(rcvBufSizeKey,channel.GetRcvBufSize());
|
||||
|
||||
//UpdateVarMap<std::string>(rateLoggingKey,std::to_string(channel.GetRateLogging()));// string API
|
||||
UpdateVarMap<int>(rateLoggingKey,channel.GetRateLogging());
|
||||
|
||||
/*
|
||||
|
@ -369,6 +379,48 @@ int FairMQProgOptions::UpdateChannelMap(const std::string& channelName, int inde
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
// string API
|
||||
int FairMQProgOptions::UpdateChannelMap(const std::string& channelName, int index, const std::string& member, const std::string& val)
|
||||
{
|
||||
if(member == "type")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateType(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(member == "method")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateMethod(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(member == "address")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateAddress(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(member == "property")
|
||||
{
|
||||
fFairMQMap.at(channelName).at(index).UpdateProperty(val);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(member == "sndBufSize" || member == "rcvBufSize" || member == "rateLogging")
|
||||
{
|
||||
UpdateChannelMap(channelName,index,member,ConvertTo<int>(val));
|
||||
}
|
||||
|
||||
//if we get there it means something is wrong
|
||||
LOG(ERROR) << "update of FairMQChannel map failed for the following key: "
|
||||
<< channelName<<"."<<index<<"."<<member;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -17,16 +17,22 @@
|
|||
#define FAIRMQPROGOPTIONS_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "FairProgOptions.h"
|
||||
|
||||
#include "FairProgOptions.h"
|
||||
#include "FairMQEventManager.h"
|
||||
#include "FairMQChannel.h"
|
||||
|
||||
class FairMQProgOptions : public FairProgOptions
|
||||
|
||||
|
||||
class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
|
||||
{
|
||||
protected:
|
||||
typedef std::unordered_map<std::string, std::vector<FairMQChannel>> FairMQMap;
|
||||
using FairMQMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
|
||||
//using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>;// string API
|
||||
//using signal_type_ptr = boost::shared_ptr<signal_type>;// string API
|
||||
|
||||
public:
|
||||
FairMQProgOptions();
|
||||
|
@ -52,9 +58,6 @@ class FairMQProgOptions : public FairProgOptions
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FairMQMap GetFairMQMap()
|
||||
{
|
||||
return fFairMQMap;
|
||||
|
@ -77,30 +80,156 @@ class FairMQProgOptions : public FairProgOptions
|
|||
// - if UpdateChannelMap(const FairMQMap& map) method is called
|
||||
// - if UserParser template method is called (it is called in the ParseAll method if json or xml MQ-config files is provided)
|
||||
|
||||
template<typename T>
|
||||
int UpdateValue(const std::string& key, const T& val)
|
||||
|
||||
/* // string API
|
||||
|
||||
//overload for string literal
|
||||
int UpdateValue(const std::string& key, const char* val) // string API
|
||||
{
|
||||
UpdateVarMap(key,val);
|
||||
|
||||
if(fMQKeyMap.count(key))
|
||||
UpdateValue(key,std::string(val));
|
||||
return 0;
|
||||
}
|
||||
// overload for string values
|
||||
int UpdateValue(const std::string& key, const std::string& val) // string API
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string channelName;
|
||||
int index = 0;
|
||||
std::string member;
|
||||
std::tie(channelName, index, member) = fMQKeyMap.at(key);
|
||||
if(fVarMap.count(key))
|
||||
{
|
||||
|
||||
|
||||
if(!fairmq::is_this_type<std::string>(fVarMap.at(key)))
|
||||
{
|
||||
LOG(ERROR) << "You try to update a value as string (for key="<< key <<") while it has been defined with a different type in the option description.";
|
||||
abort();
|
||||
}
|
||||
|
||||
// update variable map
|
||||
UpdateVarMap(key,val);
|
||||
|
||||
if(fMQKeyMap.count(key))
|
||||
{
|
||||
std::string channelName;
|
||||
int index = 0;
|
||||
std::string member;
|
||||
std::tie(channelName, index, member) = fMQKeyMap.at(key);
|
||||
UpdateChannelMap(channelName, index, member, val);
|
||||
}
|
||||
|
||||
// execute stored function of a given key if exist
|
||||
//if(std::is_same<T, int>::value || std::is_same<T, std::string>::value)//if one wants to restrict type
|
||||
if(fSignalMap.count(key))
|
||||
EmitUpdate(key,val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
LOG(ERROR) <<"UpdatedValue failed because the provided key '"
|
||||
<<key
|
||||
<<"' is not found in the variable map";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG(ERROR) << "Caught exception on key "<<key;
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//overload for string literal
|
||||
/*int UpdateValue(const std::string& key, const char* val) // string API
|
||||
{
|
||||
UpdateValue<std::string>(key,val);
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
|
||||
// specialization/overloading for string, pass by const ref
|
||||
int UpdateValue(const std::string& key, const std::string& val) // string API
|
||||
{
|
||||
UpdateValue(key,val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UpdateValue(const std::string& key, const char* val) // string API
|
||||
{
|
||||
UpdateValue<std::string>(key,std::string(val));
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int UpdateValue(const std::string& key, T val)
|
||||
{
|
||||
|
||||
if(fVarMap.count(key))
|
||||
{
|
||||
// update variable map
|
||||
UpdateVarMap<typename std::decay<T>::type>(key,val);
|
||||
|
||||
// update FairMQChannel map, check first if data are int or string
|
||||
if(std::is_same<T, int>::value || std::is_same<T, std::string>::value)
|
||||
UpdateChannelMap(channelName, index, member, val);
|
||||
if(fMQKeyMap.count(key))
|
||||
{
|
||||
std::string channelName;
|
||||
int index = 0;
|
||||
std::string member;
|
||||
std::tie(channelName, index, member) = fMQKeyMap.at(key);
|
||||
UpdateChannelMap(channelName, index, member, val);
|
||||
}
|
||||
|
||||
// execute stored function of a given key if exist
|
||||
//if(std::is_same<T, int>::value || std::is_same<T, std::string>::value)//if one wants to restrict type
|
||||
if(EventKeyFound(key))
|
||||
EmitUpdate<typename std::decay<T>::type >(key,val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
LOG(ERROR) <<"UpdatedValue failed because the provided key '"
|
||||
<<key
|
||||
<<"' is not found in the variable map";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename F>
|
||||
void Subscribe(const std::string& key, F&& func)
|
||||
{
|
||||
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
|
||||
"In template member FairMQProgOptions::Subscribe<T>(key,Lambda) the types const char* or char* for the calback signatures are not supported.");
|
||||
|
||||
if(fVarMap.count(key))
|
||||
FairMQEventManager::Connect<EventId::UpdateParam,T>(key,std::forward<F>(func));
|
||||
}
|
||||
|
||||
/*
|
||||
template <typename F>
|
||||
void Subscribe(const std::string& key, F&& func)
|
||||
{
|
||||
if(fVarMap.count(key))
|
||||
{
|
||||
//if key-value not yet found, then add it
|
||||
if(fSignalMap.find(key) == fSignalMap.end())
|
||||
fSignalMap.emplace(key, boost::make_shared<signal_type>());
|
||||
(*fSignalMap.at(key)).connect(std::forward<F>(func));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// replace FairMQChannelMap, and update variable map accordingly
|
||||
int UpdateChannelMap(const FairMQMap& map);
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
po::options_description fMQParserOptions;
|
||||
po::options_description fMQOptionsInCfg;
|
||||
|
@ -109,6 +238,21 @@ class FairMQProgOptions : public FairProgOptions
|
|||
std::string fHelpTitle;
|
||||
std::string fVersion;
|
||||
|
||||
|
||||
|
||||
|
||||
bool EventKeyFound(const std::string& key)
|
||||
{
|
||||
if (
|
||||
FairMQEventManager::EventKeyFound<EventId::UpdateParam>(key)
|
||||
)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef std::tuple<std::string,int,std::string> MQKey;//store key info
|
||||
std::map<std::string,MQKey> fMQKeyMap;// key=full path - val=key info
|
||||
|
||||
|
@ -120,7 +264,31 @@ class FairMQProgOptions : public FairProgOptions
|
|||
void UpdateMQValues();
|
||||
int Store(const FairMQMap& channels);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
// string API
|
||||
std::map<std::string, signal_type_ptr > fSignalMap;
|
||||
void EmitUpdate(const std::string& key, const char* val)
|
||||
{
|
||||
EmitUpdate(key,std::string(val));
|
||||
}
|
||||
void EmitUpdate(const std::string& key, const std::string& val)
|
||||
{
|
||||
(*fSignalMap.at(key))(key,val);
|
||||
}
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
void EmitUpdate(const std::string& key, T val)
|
||||
{
|
||||
//compile time check whether T is const char* or char*, and in that case a compile time error is thrown.
|
||||
static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
|
||||
"In template member FairMQProgOptions::EmitUpdate<T>(key,val) the types const char* or char* for the calback signatures are not supported.");
|
||||
Emit<EventId::UpdateParam,T>(key,key,val);
|
||||
}
|
||||
|
||||
int UpdateChannelMap(const std::string& channelName, int index, const std::string& member, const std::string& val);
|
||||
int UpdateChannelMap(const std::string& channelName, int index, const std::string& member, int val);
|
||||
// for cases other than int and string
|
||||
|
|
|
@ -92,6 +92,21 @@ int FairProgOptions::AddToCfgFileOptions(const po::options_description& optDesc,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
//*
|
||||
po::options_description& FairProgOptions::GetCmdLineOptions()
|
||||
{
|
||||
return fCmdLineOptions;
|
||||
}
|
||||
|
||||
po::options_description& FairProgOptions::GetCfgFileOptions()
|
||||
{
|
||||
return fConfigFileOptions;
|
||||
}
|
||||
|
||||
po::options_description& FairProgOptions::GetEnvironmentOptions()
|
||||
{
|
||||
return fEnvironmentDesc;
|
||||
}
|
||||
|
||||
int FairProgOptions::AddToEnvironmentOptions(const po::options_description& optDesc)
|
||||
{
|
||||
|
@ -153,7 +168,7 @@ int FairProgOptions::ParseCfgFile(ifstream& ifs, const po::options_description&
|
|||
{
|
||||
if (!ifs)
|
||||
{
|
||||
cout << "can not open configuration file \n";
|
||||
LOG(ERROR) << "can not open configuration file";
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
@ -169,7 +184,7 @@ int FairProgOptions::ParseCfgFile(const string& filename, const po::options_desc
|
|||
ifstream ifs(filename.c_str());
|
||||
if (!ifs)
|
||||
{
|
||||
cout << "can not open configuration file: " << filename << "\n";
|
||||
LOG(ERROR) << "can not open configuration file: " << filename;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -68,6 +68,9 @@ class FairProgOptions
|
|||
int AddToCmdLineOptions(const po::options_description& optDesc, bool visible = true);
|
||||
int AddToCfgFileOptions(const po::options_description& optDesc, bool visible = true);
|
||||
int AddToEnvironmentOptions(const po::options_description& optDesc);
|
||||
po::options_description& GetCmdLineOptions();
|
||||
po::options_description& GetCfgFileOptions();
|
||||
po::options_description& GetEnvironmentOptions();
|
||||
|
||||
void UseConfigFile(const std::string& filename = "");
|
||||
|
||||
|
@ -96,6 +99,23 @@ class FairProgOptions
|
|||
// convert value to string that corresponds to the key
|
||||
std::string GetStringValue(const std::string& key);
|
||||
|
||||
//restrict conversion to fundamental types
|
||||
template<typename T>
|
||||
T ConvertTo(const std::string& str_value)
|
||||
{
|
||||
if (std::is_arithmetic<T>::value)
|
||||
{
|
||||
std::istringstream iss( str_value );
|
||||
T val;
|
||||
iss >> val;
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR)<<"the provided string "<<str_value << " cannot be converted in the requested type. The target types must be arithmetic types";
|
||||
}
|
||||
}
|
||||
|
||||
const po::variables_map& GetVarMap() const { return fVarMap; }
|
||||
|
||||
// boost prog options parsers
|
||||
|
|
Loading…
Reference in New Issue
Block a user