TableMemberRegistry.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_types_detail_TableMemberRegistry_h
2 #define fhiclcpp_types_detail_TableMemberRegistry_h
3 
4 // ========================================================================
5 // 'TableMemberRegistry' exists solely because C++ does not have the
6 // reflection facilities required to return the members of a struct or
7 // class, which is needed to walk through the members of a table. For
8 // example, consider the following struct and associated Table<S>
9 // object:
10 //
11 // struct S {
12 // Atom<int> num{Name("num")};
13 // Sequence<int> list{Name("list")};
14 // };
15 // Table<S> t{Name("t")};
16 //
17 // C++ does not have the ability to return the list of data members
18 // for the struct 'S'. The registration system below, however, does
19 // do this by taking the Name values above ("num" and "list"), and
20 // emplacing them into a container corresponding to the table members
21 // associated with 't'.
22 //
23 // The way this registry is used is via private inheritance of a
24 // 'RegisterIfTableMember' auxiliary class. Each fhiclcpp parameter
25 // type (Atom, Sequence, etc.), inherits from the auxiliary class.
26 //
27 // If the C++ reflection facilities improve to the level that a
28 // struct's or class's members can be returned (either at
29 // compile-time, or run-time), this registry should be removed.
30 // =============================================================================
31 
32 #include "cetlib/exempt_ptr.h"
36 
37 #include <stack>
38 #include <vector>
39 
40 namespace fhicl {
41 
42  class ParameterSet;
43 
44  namespace detail {
45 
46  // All-private class that only
47  // fhicl::detail::RegisterIfTableMember, fhicl::Table, and
48  // fhicl::OptionalTable can access via friendship.
49 
51 
53  using table_members_t = std::vector<base_ptr>;
54  std::stack<table_members_t> tables_;
55 
56  static TableMemberRegistry&
58  {
59  // The use of the registry is restricted to the construction
60  // of fhiclcpp types. As construction happens on only one
61  // thread, it is sufficient for each thread to have its own
62  // copy. Although a thread-local static would be appropriate
63  // here, not all implementations adequately support
64  // thread-local variables for the use case here. We thus use
65  // a custom-built per-thread cache.
67  return registry.slot_for_current_thread();
68  }
69 
70  // Retrieval facilities for fhicl::(Optional)Table
71 
72  template <typename T, typename KeysToIgnore>
73  friend class fhicl::Table;
74  template <typename T>
75  friend class fhicl::OptionalTable;
76 
77  static std::vector<base_ptr>
79  {
80  auto& tables = instance_().tables_;
81  auto result = std::exchange(tables.top(), {});
82  tables.pop();
83  return result;
84  }
85 
86  // Registration facilities
87 
88  friend class RegisterIfTableMember;
89  static void
91  {
92  instance_().tables_.top().emplace_back(pb);
93  }
94 
95  static void
97  {
98  instance_().tables_.emplace();
99  }
100  };
101 
102  //========================================================
104  public:
106  {
107  if (is_table_member(pb->key())) {
109  }
110  if (is_table(pb->parameter_type())) {
112  }
113  }
114  };
115  }
116 }
117 
118 #endif /* fhiclcpp_types_detail_TableMemberRegistry_h */
119 
120 // Local variables:
121 // mode: c++
122 // End:
static void emplace_table_member(ParameterBase *pb)
static QCString result
std::stack< table_members_t > tables_
std::vector< base_ptr > table_members_t
par_type parameter_type() const
Definition: ParameterBase.h:68
std::string const & key() const
Definition: ParameterBase.h:38
bool is_table_member(std::string const &key)
bool is_table(std::any const &val)
Definition: coding.h:55
static constexpr double pb
Definition: Units.h:82
static TableMemberRegistry & instance_()
static std::vector< base_ptr > release_members()