I was tasked with refactoring our existing IniReader
class, which is Windows only compatible, to be cross-platform ( specifically UNIX compatible ). We decided that boost::property_tree
was a good fit for this and a quick play with property_tree confirms this.
The original class had many readValue
overloads for the various data types. During the refactoring I was happy to discover that boost::property_tree::get_value
is templatized so it made it simple to declare the following new readValue
functions:
// read and return a value from the inifile
// throws boost::property_tree:ptree_error if not found
template <class T>
T readValue( const std::string& section, const std::string& param ) const;
// read and return value from section.param in the inifile
// if the param does not exists in the section return |defaultValue|
template <class T>
T readValue( const std::string& section, const std::string& param, const T& defaultValue ) const;
However, I later discover there's a couple of special overridden readValue
functions which accept an additional int
index. This allows values to be read using param name appended with the index value like this:
[TextFileFilters]
count=3
filter1=*.txt
filter2=*.csv
filter3=*.log
num1=50
num2=20
num3=10
Originally I thought of adding two more readValue
overrides which includes the index argument:
// read and return a value from the inifile
// throws boost::property_tree:ptree_error if not found
template <class T>
T readValue( const std::string& section, const std::string& param, const int index ) const;
// read and return value from section.param in the inifile
// if the param does not exists in the section return |defaultValue|
template <class T>
T readValue( const std::string& section, const std::string& param, const T& defaultValue, const int index ) const;
BUT, there's a problem. When using T = int
it becomes ambiguous to the compiler:
// is 3 the default int value OR the index ?
int count = ini.readValue<int>( "TextFileFilters", "num", 3 );
What I've done, currently, is to remove the 3 parameter "indexed" override of readValue
. Therefore mandating that all indexed readValue
calls must be called with the default argument. This is not ideal.
The only thoughts around this I have was to introduce an new IniPath
class, which attempts to replace the section, param or section, param, index combinations:
class IniPath
{
public:
IniPath( const std::string& section, const std::string& path );
IniPath( const std::string& section, const std::string& path, const int index );
};
...
template <class T>
T readValue( const IniPath& path ) const;
template <class T>
T readValue( const IniPath& path, T& defaultValue ) const;
but does that seems excessive? Too many temporaries?
int count = ini.readValue<int>( IniPath( "TextFileFilters", "count" ) );
int log_num = ini.readValue<int>( IniPath( "TextFileFilters", "num", 3 ) );
Do you have any suggestions or ideas?