Fhiclcpp types in detail » History » Version 50
« Previous -
Version 50/56
(diff) -
Next » -
Current version
Kyle Knoepfel, 12/16/2015 10:23 AM
fhiclcpp
types in detail¶
- Table of contents
- fhiclcpp types in detail
- Parameter constructors
- Standard parameters - return types
- Optional parameters - argument types
- Additional functions for Table<T>
- Common parameter accessors
Parameter constructors¶
General comments¶
- The
Name
argument is required for each of thefhiclcpp
types. - Neither the
Table<T>
parameter nor any of theOptional*
parameters support a default value. - None of the examples below include a use of the conditional configuration facility (i.e.
std::function<bool()> maybeUse
). An explanation of how users can take advantage of the facility is given here. - The
Name&&
andComment&&
references are explained here. The double-ampersand is a way of (almost unconditionally) requiring users to provide a temporary object by specifying (e.g.)Name("some_name")
for each parameter. - In addition to
Optional*
parameters not supporting default values, they also cannot be used as template arguments to anyfhiclcpp
types:Sequence< OptionalSequence<int> > e1 { ... }; // error Sequence< OptionalSequence<int,2u> > e2 { ... }; // error Sequence< OptionalTuple<int,double> > e3 { ... }; // error OptionalSequence< Sequence<int> > ok { ... }; // ok
Atom<T>
¶
Allowed constructors¶
explicit Atom(Name&&);
explicit Atom(Name&&, Comment&&);
explicit Atom(Name&&, Comment&&, std::function<bool()> maybeUse);
// c'tors supporting default values
explicit Atom(Name&&, T const& t);
explicit Atom(Name&&, Comment&&, T const& t);
explicit Atom(Name&&, Comment&&, std::function<bool()> maybeUse, T const& t);
Examples¶
Atom<int> var { Name("var") };
Atom<int> var { Name("var"), 9 };
Atom<int> var { Name("var"), Comment("A parameter description") };
Atom<int> var { Name("var"), Comment("A parameter description"), 9 };
OptionalAtom<T>
¶
Allowed constructors¶
explicit OptionalAtom(Name&&);
explicit OptionalAtom(Name&&, Comment&&);
explicit OptionalAtom(Name&&, Comment&&, std::function<bool()> maybeUse);
Examples¶
OptionalAtom<int> var { Name("var") };
OptionalAtom<int> var { Name("var"), Comment("A parameter description") };
OptionalSequence<T>
¶
This class template is used for unbounded sequences.
Allowed constructors¶
explicit OptionalSequence(Name&&);
explicit OptionalSequence(Name&&, Comment&&);
explicit OptionalSequence(Name&&, Comment&&, std::function<bool()> maybeUse);
Examples¶
OptionalSequence<int> seq { Name("seq") };
OptionalSequence<int> seq { Name("seq"), Comment("A sequence") };
OptionalSequence<T,std::size_t>
¶
This class template is used for sequences of a specific length, known at compile time.
Allowed constructors¶
explicit OptionalSequence(Name&&);
explicit OptionalSequence(Name&&, Comment&&);
explicit OptionalSequence(Name&&, Comment&&, std::function<bool()> maybeUse);
Examples¶
OptionalSequence<int,3u> seq { Name("seq") };
OptionalSequence<int,3u> seq { Name("seq"), Comment("A sequence") };
OptionalTable<T>
¶
Allowed constructors¶
explicit OptionalTable(Name&&);
explicit OptionalTable(Name&&, Comment&&);
explicit OptionalTable(Name&&, Comment&&, std::function<bool()> maybeUse);
Examples¶
OptionalTable<T> config { Name("config") };
OptionalTable<T> config { Name("config"), Comment("This describes the table") };
OptionalTuple<T...>
¶
Allowed constructors¶
explicit OptionalTuple(Name&&);
explicit OptionalTuple(Name&&, Comment&&);
explicit OptionalTuple(Name&&, Comment&&, std::function<bool()> maybeUse);
Examples¶
OptionalTuple<string,bool> tuple { Name("tuple") };
OptionalTuple<string,bool> tuple { Name("tuple"), Comment("A tuple") };
Sequence<T>
¶
This class template is used for unbounded sequences. See the caveat below regarding narrowing conversions.
Allowed constructors¶
explicit Sequence(Name&&);
explicit Sequence(Name&&, Comment&&);
explicit Sequence(Name&&, Comment&&, std::function<bool()> maybeUse);
// c'tors supporting default values
explicit Sequence(Name&&, std::vector<T> const& t);
explicit Sequence(Name&&, Comment&&, std::vector<T> const& t);
explicit Sequence(Name&&, Comment&&, std::function<bool()> maybeUse, std::vector<T> const& t);
Examples¶
Sequence<int> seq { Name("seq") };
Sequence<int> seq { Name("seq"), Comment("A sequence") };
Sequence<int> seq { Name("seq"), std::vector<int>{ 4, 5, 6, 7 } };
Sequence<int> seq { Name("seq"), { 4, 5, 6, 7 } };
Sequence<int> seq { Name("seq"), Comment("A sequence"), std::vector<int>{ 4, 5, 6, 7 } };
Sequence<int> seq { Name("seq"), Comment("A sequence"), { 4, 5, 6, 7 } };
Precaution regarding narrowing conversions and std::initializer_list
objects¶
The following configuration will trigger a compilation warning:
Sequence<int> seq1 { Name("seq1"), std::vector<int>{ 1, 2.4e-4 } };
Sequence<int> seq2 { Name("seq2"), { 1, 2.4e-4 } };
that looks similar to this:
warning: narrowing conversion of ‘2.4000000000000001e-4’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
For build systems that convert compile-time warnings to errors, this will result in a build failure. The warning results from the nature of an std::initializer_list
object (also referred to as a brace-enclosed initializer), signified by '{1, 2.4e-4}'
, which is used to initialize the sequence objects. For std::initializer_list
objects, narrowing conversions are not allowed--that is, converting a double
to an int
is an example of narrowing that results in loss of information. This is the most likely example of where you may find a narrowing conversion.
Sequence<T,std::size_t>
¶
This class template is used for sequences of a specific length, known at compile time.
Allowed constructors¶
The dtype
is a type alias that allows users to specify as a default argument either an std::array<T,N>
object or a brace-enclosed std::initializer_list<T>
object. It is preferred that users provide an std::array
object as a default value since the size of the supplied array is checked against the expected size at compile time.
explicit Sequence(Name&&);
explicit Sequence(Name&&, Comment&&);
explicit Sequence(Name&&, Comment&&, std::function<bool()> maybeUse);
// c'tors supporting default values
explicit Sequence(Name&&, dtype const& t);
explicit Sequence(Name&&, Comment&&, dtype const& t);
explicit Sequence(Name&&, Comment&&, std::function<bool()> maybeUse, dtype const& t);
Examples¶
Sequence<int,3u> seq { Name("seq") };
Sequence<int,3u> seq { Name("seq"), Comment("A sequence") };
Sequence<int,3u> seq { Name("seq"), std::array<int,3u>{ 4, 5, 6 } };
Sequence<int,3u> seq { Name("seq"), { 4, 5, 6 } };
Sequence<int,3u> seq { Name("seq"), Comment("A sequence"), std::array<int,3u>{ 4, 5, 6 } };
Sequence<int,3u> seq { Name("seq"), Comment("A sequence"), { 4, 5, 6 } };
The warning regarding narrowing conversions above applies for bounded sequences as well.
Table<T>
¶
Allowed constructors¶
explicit Table(Name&&);
explicit Table(Name&&, Comment&&);
explicit Table(Name&&, Comment&&, std::function<bool()> maybeUse);
Examples¶
Table<T> config { Name("config") };
Table<T> config { Name("config"), Comment("This describes the table") };
Tuple<T...>
¶
Allowed constructors¶
The dtype
is a type alias that allows users to specify as a default argument either an std::tuple<T...>
object or a brace-enclosed initializer, which, in this case, is not an std::initializer_list
object.
explicit Tuple(Name&&);
explicit Tuple(Name&&, Comment&&);
explicit Tuple(Name&&, Comment&&, std::function<bool()> maybeUse);
// c'tors supporting default values
explicit Tuple(Name&&, dtype const& t);
explicit Tuple(Name&&, Comment&&, dtype const& t);
explicit Tuple(Name&&, Comment&&, std::function<bool()> maybeUse, dtype const& t);
Examples¶
Tuple<string,bool> tuple { Name("tuple") };
Tuple<string,bool> tuple { Name("tuple"), Comment("A tuple") };
Tuple<string,bool> tuple { Name("tuple"), std::tuple<string,bool>{"explicit?", true} };
Tuple<string,bool> tuple { Name("tuple"), {"compact?", true } };
Tuple<string,bool> tuple { Name("tuple"), Comment("A tuple"), std::tuple<string,bool>{ "Particle physics is neat.", true } };
Tuple<string,bool> tuple { Name("tuple"), Comment("A tuple"), { "This is false", false } };
Standard parameters - return types¶
[ In what follows, array
, string
, tuple
, and vector
should each be prefaced with the appropriate namespace resolution: 'std::
'. ]
fhiclcpp parameter |
Function call | Return type |
Simple fhiclcpp parameters |
||
Atom<string> label ; |
label() |
string const& |
Sequence<int> counts ; |
counts() |
vector<int> |
counts(1) |
int |
|
Sequence<double, 3u> point ; |
point() |
array<double, 3u> |
point(0) |
double |
|
Tuple<string, double> assoc; |
assoc() |
tuple<string, double> |
assoc.get<0>() |
string |
|
assoc.get<double>() |
double |
|
Table<Config> config; |
config() |
Config const& |
Nested fhiclcpp parameters |
||
Sequence< Sequence<int> > datasets; |
datasets() |
vector< vector<int> > |
datasets(17) |
vector<int> |
|
Sequence< Sequence<int>, 2u > twoDatasets; |
twoDatasets() |
array< vector<int>, 2u > |
twoDatasets(1) |
vector<int> |
|
Sequence< Sequence<int, 2u> > intPairs; |
intPairs() |
vector< array<int, 2u> > |
intPairs(42) |
array<int, 2u> |
|
Sequence< Tuple<string, int, bool> > triplets; |
triplets() |
vector< tuple<string, int, bool> > |
triplets(3) |
tuple<string, int, bool> |
|
Sequence< Table<Config> > manyConfigTables; |
manyConfigTables() |
vector< Config > |
manyConfigTables(6) |
Config const& |
|
Tuple< string, Table<Config> > configAssoc; |
configAssoc() |
tuple< string, Config > |
configAssoc.get<0>() |
string |
|
configAssoc.get<1>() |
Config |
|
Tuple< Tuple<string,bool>, Sequence<int> > awkward; |
awkward() |
tuple< tuple<string, bool>, vector<int> > |
awkward.get<0>() |
tuple<string,bool> |
|
awkward.get<1>() |
vector<int> |
Optional
parameters - argument types¶
The usage pattern for Optional
fhiclcpp
parameters is:
OptionalAtom<string> message { Name("message") };
string filled_msg; // passed argument
if ( message(filled_msg) ) {
// use 'filled_msg'
}
The following table gives the required passed-argument types for a given Optional
parameter.
[ In what follows, array
, string
, tuple
, and vector
should each be prefaced with the appropriate namespace resolution: 'std::
'. ]
fhiclcpp parameter |
Passed argument | Function call |
Simple fhiclcpp parameters |
||
OptionalAtom<string> label ; |
string l; |
bool exists = label(l); |
OptionalSequence<int> counts ; |
vector<int> v; |
bool exists = counts(v); |
OptionalSequence<double, 3u> point ; |
array<double, 3u> p; |
bool exists = point(p); |
OptionalTuple<string, double> assoc; |
tuple<string, double> t; |
bool exists = assoc(t); |
OptionalTable<Config> config; |
Config c; |
bool exists = config(c); |
Nested fhiclcpp parameters |
||
OptionalSequence< Sequence<int> > datasets; |
vector< vector<int> > sets; |
bool exists = datasets(sets); |
OptionalSequence< Sequence<int>, 2u > twoDatasets; |
array< vector<int>, 2u > sets; |
bool exists = twoDatasets(sets); |
OptionalSequence< Sequence<int, 2u> > intPairs; |
vector< array<int, 2u> > prs; |
bool exists = intPairs(prs); |
OptionalSequence< Tuple<string, int, bool> > triplets; |
vector< tuple<string, int, bool> > trps; |
bool exists = triplets(trps); |
OptionalSequence< Table<Config> > manyConfigTables; |
vector< Config > tbls; |
bool exists = manyConfigTables(tbls); |
OptionalTuple< string, Table<Config> > configAssoc; |
tuple< string, Config > assoc; |
bool exists = configAssoc(assoc); |
OptionalTuple< Tuple<string,bool>, Sequence<int> > awkward; |
tuple< tuple<string, bool>, vector<int> > wow; |
bool exists = awkward(wow); |
Additional functions for Table<T>
¶
The Table
template offers a few extra functions that the user can call:
fhicl::ParameterSet const& get_PSet() const;
void print_allowed_configuration(std::ostream& os,
std::string const& tab = std::string(3,' ') ) const;
// Expert-level functions
void validate_ParameterSet(fhicl::ParameterSet const& pset,
std::set<std::string> const& keysToIgnore = {} );
get_PSet
¶
A call to this function returns a const
reference to the ParameterSet
object that was used to fill the values of the individual Table
members. This is helpful for users who need to interact with the ParameterSet
object itself.
print_allowed_configuration
¶
For any Table<Config>
object, print_allowed_configuration
will fill a user-supplied std::ostream
object with the allowed configuration as defined by the Config
struct. The optional second argument specifies the number of spaces per indentation. The default is 3 spaces but is, of course, user-configurable.
[ N.B. The following function should not normally be invoked by users. It is meant to be called only in contexts outside of art
. Please consult artists@fnal.gov for guidance.]
validate_ParameterSet
(expert)¶
This function is intended for experts who need to validate the pset
object themselves. The keysToIgnore
variable represents a set of keys for which the validation step will ignore. The validation function will ignore any nested keys as well--i.e. if a user specifies an ignorable key as table1
, the (e.g.) table1.someAtom
key would be ignored in addition to just the table1
name. An indexed parameter (e.g.) seq[1]
is considered a nested parameter of its parent seq
. Providing or not providing the ignorable key in a configuration will lead to no error upon validation of the ParameterSet
.
Should the validation step fail, an exception is thrown of type fhicl::detail::validationException
. This behavior is not currently configurable.
Common parameter accessors¶
Each of the fhiclcpp
types has the following accessors:
std::string key() const;
std::string name() const;
std::string comment() const;
bool has_default() const;
bool is_optional() const;
bool is_conditional() const;
par_type parameter_type() const;
bool should_use() const;
To call these functions, the difference in syntax is crucial:
Atom<int> val { Name("val") };
auto key1 = val.key(); // correct
auto key2 = val().key(); // ! compile-time ERROR - 'val()' is an int, which has no accessor called 'key()'
key()
¶
A call to key()
returns the full key, including all enclosing tables. For example, consider a module that is designed to allow the following configuration:
pset: {
list: [ { particle: electron },
{ particle: muon } ]
}
For a suitably declared set of fhiclcpp
parameters, the returned key corresponding to "muon" would be pset.list[1].particle
.
name()
¶
The name is the most-nested name in the key. For the above "muon" parameter, a key of pset.list[1].particle
has a corresponding name of particle
. If the parameter in question were pset.list[1]
, the name would be1 list[1]
.
1 Technically, this is inaccurate -- sequence elements do not have names. However, for the sake of parameter identification, a sequence element has a name whose value is the sequence name with the appropriate sequence element index/indices appended.
comment()
¶
Returns the comment supplied as the string literal in (e.g.) Comment("Here is the comment")
. If no Comment
argument is provided in the fhiclcpp
parameter constructor, a call to this function returns an empty string.
has_default()
¶
Returns true
or false
depending on whether the user supplied a default value for the parameter.
is_optional()
¶
Returns true
if the parameter is an Optional*
fhiclcpp
type; false
otherwise.
is_conditional()
¶
Returns true
if a configuration predicate (either through fhicl::use_if
, fhicl::use_unless
, or some supplied lambda function) has been provided by the user; false
otherwise.
parameter_type()
¶
Returns an enumeration value based on the parameter type:
enum class par_type {
ATOM, // (Optional)Atom<T>
TABLE, // (Optional)Table<T>
SEQ_VECTOR, // (Optional)Sequence<T>
SEQ_ARRAY, // (Optional)Sequence<T,std::size_t>
TUPLE, // (Optional)Tuple<T...>
NTYPES // Signifies invalid parameter
};
should_use()
¶
Returns true
unless a user-provided configuration predicate returns false
.