25
25
#ifndef FABLE_SCHEMA_INTERFACE_HPP_
26
26
#define FABLE_SCHEMA_INTERFACE_HPP_
27
27
28
- #include < memory> // for shared_ptr<>
29
- #include < string> // for string
30
- #include < utility> // for move
28
+ #include < memory> // for shared_ptr<>
29
+ #include < string> // for string
30
+ #include < type_traits> // for enable_if_t<>, is_base_of<>
31
+ #include < utility> // for move
31
32
32
33
#include < fable/conf.hpp> // for Conf
33
34
#include < fable/error.hpp> // for SchemaError
@@ -234,10 +235,21 @@ class Interface {
234
235
virtual void reset_ptr () = 0;
235
236
};
236
237
238
+ /* *
239
+ * Use SFINAE mechanism to disable a template function when S is not a subclass
240
+ * of Interface, hence not a schema.
241
+ *
242
+ * \example
243
+ * template<typename S, typename = enable_if_schema_t<S>>
244
+ * void foobar(S schema);
245
+ */
246
+ template <typename S>
247
+ using enable_if_schema_t = std::enable_if_t <std::is_base_of<Interface, S>::value>;
248
+
237
249
// ------------------------------------------------------------------------- //
238
250
239
251
class Box : public Interface {
240
- public:
252
+ public: // Constructors
241
253
Box () = default ;
242
254
Box (const Box&) = default ;
243
255
Box (Box&&) = default ;
@@ -246,7 +258,13 @@ class Box : public Interface {
246
258
Box (Interface* i) : impl_(i) { assert (impl_); } // NOLINT
247
259
Box (std::shared_ptr<Interface> i) : impl_(std::move(i)) { assert (impl_); } // NOLINT
248
260
249
- public:
261
+ public: // Special
262
+ template <typename T>
263
+ std::shared_ptr<const T> as () const {
264
+ return std::dynamic_pointer_cast<T>(impl_);
265
+ }
266
+
267
+ public: // Overrides
250
268
Interface* clone () const override { return impl_->clone (); }
251
269
JsonType type () const override { return impl_->type (); }
252
270
std::string type_string () const override { return impl_->type_string (); }
@@ -355,6 +373,28 @@ class Base : public Interface {
355
373
356
374
// ------------------------------------------------------------------------- //
357
375
376
+ /* *
377
+ * Use SFINAE mechanism to disable a template function when S is not a subclass
378
+ * of Confable.
379
+ *
380
+ * \example
381
+ * template<typename T, typename = enable_if_confable_t<T>>
382
+ * void foobar(T x);
383
+ */
384
+ template <typename T>
385
+ using enable_if_confable_t = std::enable_if_t <std::is_base_of<Confable, T>::value>;
386
+
387
+ /* *
388
+ * Use SFINAE mechanism to disable a template function when S is a subclass
389
+ * of Confable.
390
+ *
391
+ * \example
392
+ * template<typename T, typename = enable_if_not_confable_t<T>>
393
+ * void foobar(T x);
394
+ */
395
+ template <typename T>
396
+ using enable_if_not_confable_t = std::enable_if_t <!std::is_base_of<Confable, T>::value>;
397
+
358
398
template <typename T, std::enable_if_t <std::is_base_of<Confable, T>::value, int > = 0 >
359
399
auto make_prototype (std::string&& desc = " " );
360
400
0 commit comments