9 #ifndef CORE_DERIVED_MODULE_
10 #define CORE_DERIVED_MODULE_
12 #include "boost/any.hpp"
13 #include "boost/mpl/at.hpp"
14 #include "boost/mpl/find_if.hpp"
15 #include "boost/mpl/for_each.hpp"
16 #include "boost/mpl/map.hpp"
17 #include "boost/mpl/size.hpp"
18 #include "boost/mpl/size_t.hpp"
19 #include "boost/mpl/vector.hpp"
29 namespace DerivedModule {
33 inline bool caseInsensitiveEqual(
const std::string& a,
const std::string& b) {
34 return std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b),
35 [](
const char x,
const char y) ->
bool { return ::tolower(x) == ::tolower(y); });
39 template<
bool done = true>
41 template<
typename Iter,
typename LastIter,
typename Pred,
typename Exec>
42 static auto execute(Iter* , LastIter* ,
const Pred& ,
const Exec & ) ->
43 typename Exec::ResultType {
51 template<
typename Iter,
typename LastIter,
typename Pred,
typename Exec>
52 static auto execute(Iter* , LastIter* ,
const Pred& p,
const Exec& e) ->
typename Exec::ResultType {
53 using Item =
typename boost::mpl::deref<Iter>::type;
55 if (!p(static_cast<Item*>(0))) {
56 using Next =
typename boost::mpl::next<Iter>::type;
58 static_cast<LastIter*>(0), p, e);
61 return e(static_cast<Item*>(0));
82 template<
typename Sequence,
typename Predicate,
typename Executable>
83 inline auto exec_if(
const Predicate& p,
const Executable& e, Sequence* = 0) ->
typename Executable::ResultType {
84 BOOST_MPL_ASSERT((boost::mpl::is_sequence<Sequence>));
85 using First =
typename boost::mpl::begin<Sequence>::type;
86 using Last =
typename boost::mpl::end<Sequence>::type;
96 template<
typename PairType>
97 bool operator()(PairType* = 0)
const {
98 using InterfaceType =
typename boost::mpl::first<PairType>::type;
99 return caseInsensitiveEqual(identifier, InterfaceType::interface);
102 std::string identifier;
110 template<
typename ModelType>
111 bool operator()(ModelType* = 0)
const {
112 return caseInsensitiveEqual(identifier, ModelType::model);
115 std::string identifier;
119 template<
typename InterfaceType>
121 using InterfaceTypePtr = std::shared_ptr<InterfaceType>;
122 using ResultType = boost::any;
124 template<
typename ModelType>
125 ResultType operator()(ModelType* = 0)
const {
126 return static_cast<InterfaceTypePtr
>(std::make_shared<ModelType>());
129 static ResultType none() {
136 ResolveModel(std::string
id) : identifier(std::move(
id)) {
139 using ResultType = boost::any;
141 template<
typename PairType>
142 boost::any operator()(PairType* = 0)
const {
143 using InterfaceType =
typename boost::mpl::first<PairType>::type;
144 using ModelTypeList =
typename boost::mpl::second<PairType>::type;
150 static ResultType none() {
154 std::string identifier;
159 using ResultType = bool;
162 ResultType operator()(T* = 0)
const {
166 static ResultType none() {
173 ModelExists(std::string
id) : identifier(std::move(
id)) {
176 using ResultType = bool;
178 template<
typename PairType>
179 ResultType operator()(PairType* = 0)
const {
180 using ModelTypeList =
typename boost::mpl::second<PairType>::type;
185 static ResultType none() {
189 std::string identifier;
194 using ResultType = std::vector<std::string>;
196 template<
typename PairType>
197 ResultType operator()(PairType* = 0)
const {
198 using ModelTypeList =
typename boost::mpl::second<PairType>::type;
200 std::vector<std::string> models;
201 models.reserve(boost::mpl::size<ModelTypeList>::value);
203 boost::mpl::for_each<ModelTypeList, boost::mpl::make_identity<boost::mpl::_1>>([&](
auto t) {
204 using ModelType =
typename decltype(t)::type;
205 models.push_back(ModelType::model);
211 static ResultType none() {
217 constexpr
bool strEqual(
const char* a,
const char* b) {
218 return *a == *b && (*a ==
'\0' || strEqual(a + 1, b + 1));
222 template<
typename... ModelTypes>
223 constexpr
bool identifiersOverlap() {
224 constexpr std::size_t S =
sizeof...(ModelTypes);
226 const std::array<const char*, S> typeIdentifiers{ModelTypes::model...};
228 for (
unsigned i = 0; i < S; ++i) {
229 for (
unsigned j = i + 1; j < S; ++j) {
230 if (strEqual(typeIdentifiers.at(i), typeIdentifiers.at(j))) {
240 template<
typename MPLVector, std::size_t... Inds>
241 constexpr
bool identifierOverlapForwarder(std::index_sequence<Inds...> ) {
242 return identifiersOverlap<typename boost::mpl::at<MPLVector, boost::mpl::size_t<Inds>>::type...>();
247 template<
typename MPLMapIterPair>
249 : std::integral_constant<
250 bool, identifierOverlapForwarder<typename boost::mpl::second<MPLMapIterPair>::type>(
251 std::make_index_sequence<boost::mpl::size<typename boost::mpl::second<MPLMapIterPair>::type>::type::value>{})> {
257 template<
typename MPLMapIterPair>
259 : std::integral_constant<bool, boost::mpl::size<typename boost::mpl::second<MPLMapIterPair>::type>::value == 0> {};
262 template<
typename Sequence,
typename Predicate>
264 : boost::is_same<typename boost::mpl::end<Sequence>::type, typename boost::mpl::find_if<Sequence, Predicate>::type> {};
267 template<
typename MPLMap>
271 template<
typename MPLMap>
335 template<
typename MPLMap>
336 boost::any resolve(
const std::string& interface,
const std::string& model) {
340 "Model identifiers overlap within a single model type list! Model identifiers must be unique within an "
356 template<
typename MPLMap>
357 bool has(
const std::string& interface,
const std::string& model) noexcept {
358 return detail::exec_if<MPLMap>(detail::MapPairInterfaceIdentifierMatches{interface}, detail::ModelExists{model});
369 template<
typename MPLMap>
370 std::vector<std::string> announceInterfaces() noexcept {
371 std::vector<std::string> interface;
372 interface.reserve(boost::mpl::size<MPLMap>::value);
374 boost::mpl::for_each<MPLMap, boost::mpl::make_identity<boost::mpl::_1>>([&](
auto p) {
375 using PairType =
typename decltype(p)::type;
376 using InterfaceType =
typename boost::mpl::first<PairType>::type;
377 interface.push_back(InterfaceType::interface);
393 template<
typename MPLMap>
394 std::vector<std::string> announceModels(
const std::string& interface) noexcept {
395 return detail::exec_if<MPLMap>(detail::MapPairInterfaceIdentifierMatches{interface}, detail::ListModels{});
Definition: DerivedModule.h:172
Definition: DerivedModule.h:158
Definition: DerivedModule.h:40
Definition: DerivedModule.h:106
Definition: DerivedModule.h:258
Definition: DerivedModule.h:263
Definition: DerivedModule.h:272
Definition: DerivedModule.h:193
Definition: DerivedModule.h:120
Definition: DerivedModule.h:256
Definition: DerivedModule.h:268
Definition: DerivedModule.h:248
Definition: DerivedModule.h:246
Definition: DerivedModule.h:135
Definition: DerivedModule.h:92