On 07/18/2015 12:47 PM, Timo Heister wrote:
> I think the only way to do this is to get() and then split the string
> manually (like I described). We only have get(), get_int(),
> get_double(), and get_bool(). Adding something like get_list() is a
> cool idea but would require looking up the Pattern to find out things
> like separator.
Correct. The same issue would of course exist for all of the other Patterns
classes: it's not just about the return type, but possibly other information
as well that ParameterHandler doesn't know but the Pattern does (list
separators are just one example). This is why there is only get(), and the
specializations get_bool(), get_int() and get_double().
One could argue that the fact that we have these latter three is a mistake and
that ParameterHandler should only have get() and then let the user convert
things. I think they're useful, but if I had to write it again today I
probably wouldn't include them any more.
That said, I've occasionally thought that something like this would be nice:
class PatternBase {
public:
// have a function that returns a parameter's value to a type
// that's unclear here, but that derived classes specify
virtual boost::any convert_parameter_value (const std::string &) = 0;
};
template <typename PatternClass>
typename PatternClass::ReturnType
ParameterHandler::get (const std::string ¶m_name) const {
{
// look up the value, let the stored pattern convert to a
// type that matches the pattern, return it as a generic
// type so we can use the virtual function, then here
// any_cast it back to what the user wants
//
// the any_cast will fail if the template argument does
// not match the pattern you gave when the parameter was
// declared
return boost::any_cast<typename PatternClass::ReturnType>
(...look up pattern for param_name...
->convert_parameter_value (this->get (param_name)));
};
Then we could have this:
class Patterns::Integer {
public:
typedef ReturnType int;
virtual boost::any convert_parameter_value (const std::string &s)
{ return boost::lexical_cast<int>(s); }
};
and call
int i = prm.get<Patterns::Integer> ("integer_parameter");
which would do the same as we currently do with
int i = prm.get_int ("integer_parameter");
The problem is that individual patterns can only statically declare the type
of their values, i.e., Patterns::List would need to declare it as
typedef std::list<std::string> ReturnType;
or
typedef std::vector<std::string> ReturnType;
regardless whether you are using it in a context where you expect the user to
pass in a list of integers, a list of doubles, or a list of strings. In other
words, the conversion of the *inner* type does not happen; on the other hand,
one would not have to repeat the separator for the list at both the place
where the parameter is declared and the place where it is retrieved from
ParaneterHandler.
If people think that this facility would nevertheless be useful, then I'd be
happy to code this up in final form.
Best
W.
--
------------------------------------------------------------------------
Wolfgang Bangerth email:
bang...@math.tamu.edu
www:
http://www.math.tamu.edu/~bangerth/