@@ -51,6 +51,10 @@ using string_to_base_map
5151 = std::unordered_map<std::string, std::shared_ptr<base>>;
5252#endif
5353
54+ // if defined, `base` will retain type information in form of an enum class
55+ // such that static_cast can be used instead of dynamic_cast
56+ // #define CPPTOML_NO_RTTI
57+
5458template <class T >
5559class option
5660{
@@ -396,6 +400,95 @@ inline std::shared_ptr<T> make_element();
396400inline std::shared_ptr<table> make_table ();
397401inline std::shared_ptr<table_array> make_table_array ();
398402
403+ #if defined(CPPTOML_NO_RTTI)
404+ // / Base type used to store underlying data type explicitly if RTTI is disabled
405+ enum class base_type
406+ {
407+ NONE,
408+ STRING,
409+ LOCAL_TIME,
410+ LOCAL_DATE,
411+ LOCAL_DATETIME,
412+ OFFSET_DATETIME,
413+ INT,
414+ FLOAT,
415+ BOOL,
416+ TABLE,
417+ ARRAY,
418+ TABLE_ARRAY
419+ };
420+
421+ // / Type traits class to convert C++ types to enum member
422+ template <class T >
423+ struct base_type_traits ;
424+
425+ template <>
426+ struct base_type_traits <std::string>
427+ {
428+ static const base_type type = base_type::STRING;
429+ };
430+
431+ template <>
432+ struct base_type_traits <local_time>
433+ {
434+ static const base_type type = base_type::LOCAL_TIME;
435+ };
436+
437+ template <>
438+ struct base_type_traits <local_date>
439+ {
440+ static const base_type type = base_type::LOCAL_DATE;
441+ };
442+
443+ template <>
444+ struct base_type_traits <local_datetime>
445+ {
446+ static const base_type type = base_type::LOCAL_DATETIME;
447+ };
448+
449+ template <>
450+ struct base_type_traits <offset_datetime>
451+ {
452+ static const base_type type = base_type::OFFSET_DATETIME;
453+ };
454+
455+ template <>
456+ struct base_type_traits <int64_t >
457+ {
458+ static const base_type type = base_type::INT;
459+ };
460+
461+ template <>
462+ struct base_type_traits <double >
463+ {
464+ static const base_type type = base_type::FLOAT;
465+ };
466+
467+ template <>
468+ struct base_type_traits <bool >
469+ {
470+ static const base_type type = base_type::BOOL;
471+ };
472+
473+ template <>
474+ struct base_type_traits <table>
475+ {
476+ static const base_type type = base_type::TABLE;
477+ };
478+
479+ template <>
480+ struct base_type_traits <array>
481+ {
482+ static const base_type type = base_type::ARRAY;
483+ };
484+
485+ template <>
486+ struct base_type_traits <table_array>
487+ {
488+ static const base_type type = base_type::TABLE_ARRAY;
489+ };
490+ #endif
491+
399492/* *
400493 * A generic base TOML value used for type erasure.
401494 */
@@ -480,11 +573,28 @@ class base : public std::enable_shared_from_this<base>
480573 template <class Visitor , class ... Args>
481574 void accept (Visitor&& visitor, Args&&... args) const ;
482575
576+ #if defined(CPPTOML_NO_RTTI)
577+ base_type type () const
578+ {
579+ return type_;
580+ }
581+
582+ protected:
583+ base (const base_type t) : type_(t)
584+ {
585+ // nothing
586+ }
587+
588+ private:
589+ const base_type type_ = base_type::NONE;
590+
591+ #else
483592 protected:
484593 base ()
485594 {
486595 // nothing
487596 }
597+ #endif
488598};
489599
490600/* *
@@ -540,9 +650,15 @@ class value : public base
540650 /* *
541651 * Constructs a value from the given data.
542652 */
653+ #if defined(CPPTOML_NO_RTTI)
654+ value (const T& val) : base(base_type_traits<T>::type), data_(val)
655+ {
656+ }
657+ #else
543658 value (const T& val) : data_(val)
544659 {
545660 }
661+ #endif
546662
547663 value (const value& val) = delete ;
548664 value& operator =(const value& val) = delete ;
@@ -560,34 +676,71 @@ std::shared_ptr<typename value_traits<T>::type> make_value(T&& val)
560676template <class T >
561677inline std::shared_ptr<value<T>> base::as ()
562678{
679+ #if defined(CPPTOML_NO_RTTI)
680+ if (type () == base_type_traits<T>::type)
681+ return std::static_pointer_cast<value<T>>(shared_from_this ());
682+ else
683+ return nullptr ;
684+ #else
563685 return std::dynamic_pointer_cast<value<T>>(shared_from_this ());
686+ #endif
564687}
565688
566689// special case value<double> to allow getting an integer parameter as a
567690// double value
568691template <>
569692inline std::shared_ptr<value<double >> base::as ()
570693{
694+ #if defined(CPPTOML_NO_RTTI)
695+ if (type () == base_type::FLOAT)
696+ return std::static_pointer_cast<value<double >>(shared_from_this ());
697+
698+ if (type () == base_type::INT)
699+ {
700+ auto v = std::static_pointer_cast<value<int64_t >>(shared_from_this ());
701+ return make_value<double >(static_cast <double >(v->get ()));;
702+ }
703+ #else
571704 if (auto v = std::dynamic_pointer_cast<value<double >>(shared_from_this ()))
572705 return v;
573706
574707 if (auto v = std::dynamic_pointer_cast<value<int64_t >>(shared_from_this ()))
575708 return make_value<double >(static_cast <double >(v->get ()));
709+ #endif
576710
577711 return nullptr ;
578712}
579713
580714template <class T >
581715inline std::shared_ptr<const value<T>> base::as () const
582716{
717+ #if defined(CPPTOML_NO_RTTI)
718+ if (type () == base_type_traits<T>::type)
719+ return std::static_pointer_cast<const value<T>>(shared_from_this ());
720+ else
721+ return nullptr ;
722+ #else
583723 return std::dynamic_pointer_cast<const value<T>>(shared_from_this ());
724+ #endif
584725}
585726
586727// special case value<double> to allow getting an integer parameter as a
587728// double value
588729template <>
589730inline std::shared_ptr<const value<double >> base::as () const
590731{
732+ #if defined(CPPTOML_NO_RTTI)
733+ if (type () == base_type::FLOAT)
734+ return std::static_pointer_cast<const value<double >>(shared_from_this ());
735+
736+ if (type () == base_type::INT)
737+ {
738+ auto v = as<int64_t >();
739+ // the below has to be a non-const value<double> due to a bug in
740+ // libc++: https://llvm.org/bugs/show_bug.cgi?id=18843
741+ return make_value<double >(static_cast <double >(v->get ()));
742+ }
743+ #else
591744 if (auto v
592745 = std::dynamic_pointer_cast<const value<double >>(shared_from_this ()))
593746 return v;
@@ -598,6 +751,7 @@ inline std::shared_ptr<const value<double>> base::as() const
598751 // libc++: https://llvm.org/bugs/show_bug.cgi?id=18843
599752 return make_value<double >(static_cast <double >(v->get ()));
600753 }
754+ #endif
601755
602756 return nullptr ;
603757}
@@ -839,7 +993,14 @@ class array : public base
839993 }
840994
841995 private:
996+ #if defined(CPPTOML_NO_RTTI)
997+ array () : base(base_type::ARRAY)
998+ {
999+ // empty
1000+ }
1001+ #else
8421002 array () = default;
1003+ #endif
8431004
8441005 template <class InputIterator >
8451006 array (InputIterator begin, InputIterator end) : values_{begin, end}
@@ -992,10 +1153,17 @@ class table_array : public base
9921153 }
9931154
9941155 private:
1156+ #if defined(CPPTOML_NO_RTTI)
1157+ table_array () : base(base_type::TABLE_ARRAY)
1158+ {
1159+ // nothing
1160+ }
1161+ #else
9951162 table_array ()
9961163 {
9971164 // nothing
9981165 }
1166+ #endif
9991167
10001168 table_array (const table_array& obj) = delete ;
10011169 table_array& operator =(const table_array& rhs) = delete ;
@@ -1369,10 +1537,17 @@ class table : public base
13691537 }
13701538
13711539 private:
1540+ #if defined(CPPTOML_NO_RTTI)
1541+ table () : base(base_type::TABLE)
1542+ {
1543+ // nothing
1544+ }
1545+ #else
13721546 table ()
13731547 {
13741548 // nothing
13751549 }
1550+ #endif
13761551
13771552 table (const table& obj) = delete ;
13781553 table& operator =(const table& rhs) = delete ;
0 commit comments