Project

General

Profile

Fhiclcpp types in detail » History » Version 48

« Previous - Version 48/56 (diff) - Next » - Current version
Kyle Knoepfel, 12/16/2015 09:41 AM


fhiclcpp types in detail


Parameter constructors

General rules

For each of the fhiclcpp types, the following rules apply:
  • The Name argument is required.
  • Neither the Table<T> parameter nor any of the Optional* parameters support a default value.

Note about optional parameters

In addition to Optional* parameters not supporting default values, they also cannot be used as template arguments to any fhiclcpp 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 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 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.