23 friend class TOML_PARSER_TYPENAME;
28 decltype(
auto) get_value_exact()
const noexcept(impl::value_retrieval_is_nothrow<T>);
30 template <
typename T,
typename N>
31 using ref_type_ = std::conditional_t<
32 std::is_reference_v<T>,
33 impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>,
34 impl::copy_cvref<impl::unwrap_node<T>, N>
37 template <
typename T,
typename N>
38 using ref_type = std::conditional_t<
39 std::is_reference_v<N>,
41 ref_type_<T, std::add_lvalue_reference_t<N>>
44 template <
typename T,
typename N>
46 static ref_type<T, N&&> do_ref(N&& n)
noexcept
48 using unwrapped_type = impl::unwrap_node<T>;
49 static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
50 "The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
53 n.template is<unwrapped_type>()
54 &&
"template type argument provided to toml::node::ref() didn't match the node's actual type");
56 using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&;
57 using val_type = std::remove_volatile_t<unwrapped_type>;
58 using out_ref = ref_type<T, N&&>;
59 static_assert(std::is_reference_v<out_ref>);
61 if constexpr (toml::is_value<unwrapped_type>)
62 return static_cast<out_ref
>(
const_cast<node_ref
>(n).template ref_cast<val_type>().get());
64 return static_cast<out_ref
>(
const_cast<node_ref
>(n).
template ref_cast<val_type>());
72 node(
const node&)
noexcept;
75 node(node&&)
noexcept;
78 node& operator=(
const node&)
noexcept;
81 node& operator=(node&&)
noexcept;
83 template <
typename T,
typename N>
84 using ref_cast_type_ = std::conditional_t<
85 std::is_reference_v<T>,
86 impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>,
87 impl::copy_cvref<impl::wrap_node<T>, N>
90 template <
typename T,
typename N>
91 using ref_cast_type = std::conditional_t<
92 std::is_reference_v<N>,
94 ref_cast_type_<T, std::add_lvalue_reference_t<N>>
99 ref_cast_type<T, node&> ref_cast() &
noexcept
101 using out_ref = ref_cast_type<T, node&>;
102 using out_type = std::remove_reference_t<out_ref>;
103 return static_cast<out_ref
>(*
reinterpret_cast<out_type*
>(
this));
106 template <
typename T>
108 ref_cast_type<T, node&&> ref_cast() &&
noexcept
110 using out_ref = ref_cast_type<T, node&&>;
111 using out_type = std::remove_reference_t<out_ref>;
112 return static_cast<out_ref
>(*
reinterpret_cast<out_type*
>(
this));
115 template <
typename T>
117 ref_cast_type<T, const node&> ref_cast()
const&
noexcept
119 using out_ref = ref_cast_type<T, const node&>;
120 using out_type = std::remove_reference_t<out_ref>;
121 return static_cast<out_ref
>(*
reinterpret_cast<out_type*
>(
this));
124 template <
typename T>
126 ref_cast_type<T, const node&&> ref_cast()
const&&
noexcept
128 using out_ref = ref_cast_type<T, const node&&>;
129 using out_type = std::remove_reference_t<out_ref>;
130 return static_cast<out_ref
>(*
reinterpret_cast<out_type*
>(
this));
137 virtual ~node()
noexcept;
174 virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch)
noexcept = 0;
178 virtual bool is_homogeneous(node_type ntype,
const node*& first_nonmatch)
const noexcept = 0;
207 virtual bool is_homogeneous(node_type ntype)
const noexcept = 0;
235 template <
typename ElemType =
void>
237 bool is_homogeneous()
const noexcept
239 using type = impl::remove_cvref<impl::unwrap_node<ElemType>>;
240 static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>,
241 "The template type argument of node::is_homogeneous() must be void or one "
242 "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
244 return is_homogeneous(impl::node_type_of<type>);
249 virtual node_type type()
const noexcept = 0;
253 virtual bool is_table()
const noexcept = 0;
257 virtual bool is_array()
const noexcept = 0;
261 virtual bool is_array_of_tables()
const noexcept = 0;
265 virtual bool is_value()
const noexcept = 0;
269 virtual bool is_string()
const noexcept = 0;
281 virtual bool is_number()
const noexcept = 0;
289 virtual bool is_date()
const noexcept = 0;
293 virtual bool is_time()
const noexcept = 0;
304 template <
typename T>
306 bool is()
const noexcept
308 using type = impl::remove_cvref<impl::unwrap_node<T>>;
309 static_assert(toml::is_value<type> || toml::is_container<type>,
310 "The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
312 if constexpr (std::is_same_v<type, table>)
314 else if constexpr (std::is_same_v<type, array>)
316 else if constexpr (std::is_same_v<type, std::string>)
318 else if constexpr (std::is_same_v<type, int64_t>)
320 else if constexpr (std::is_same_v<type, double>)
322 else if constexpr (std::is_same_v<type, bool>)
324 else if constexpr (std::is_same_v<type, date>)
326 else if constexpr (std::is_same_v<type, time>)
328 else if constexpr (std::is_same_v<type, date_time>)
339 virtual table* as_table()
noexcept = 0;
343 virtual array* as_array()
noexcept = 0;
347 virtual toml::value<std::string>* as_string()
noexcept = 0;
351 virtual toml::value<int64_t>* as_integer()
noexcept = 0;
355 virtual toml::value<double>* as_floating_point()
noexcept = 0;
359 virtual toml::value<bool>* as_boolean()
noexcept = 0;
363 virtual toml::value<date>* as_date()
noexcept = 0;
367 virtual toml::value<time>* as_time()
noexcept = 0;
371 virtual toml::value<date_time>* as_date_time()
noexcept = 0;
375 virtual const table* as_table()
const noexcept = 0;
379 virtual const array* as_array()
const noexcept = 0;
383 virtual const toml::value<std::string>* as_string()
const noexcept = 0;
387 virtual const toml::value<int64_t>* as_integer()
const noexcept = 0;
391 virtual const toml::value<double>* as_floating_point()
const noexcept = 0;
395 virtual const toml::value<bool>* as_boolean()
const noexcept = 0;
399 virtual const toml::value<date>* as_date()
const noexcept = 0;
403 virtual const toml::value<time>* as_time()
const noexcept = 0;
407 virtual const toml::value<date_time>* as_date_time()
const noexcept = 0;
429 template <
typename T>
431 impl::wrap_node<T>* as()
noexcept
433 using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
434 static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
435 "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
437 if constexpr (std::is_same_v<unwrapped_type, table>)
439 else if constexpr (std::is_same_v<unwrapped_type, array>)
441 else if constexpr (std::is_same_v<unwrapped_type, std::string>)
443 else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
445 else if constexpr (std::is_same_v<unwrapped_type, double>)
446 return as_floating_point();
447 else if constexpr (std::is_same_v<unwrapped_type, bool>)
449 else if constexpr (std::is_same_v<unwrapped_type, date>)
451 else if constexpr (std::is_same_v<unwrapped_type, time>)
453 else if constexpr (std::is_same_v<unwrapped_type, date_time>)
454 return as_date_time();
458 template <
typename T>
460 const impl::wrap_node<T>* as()
const noexcept
462 using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
463 static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
464 "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
466 if constexpr (std::is_same_v<unwrapped_type, table>)
468 else if constexpr (std::is_same_v<unwrapped_type, array>)
470 else if constexpr (std::is_same_v<unwrapped_type, std::string>)
472 else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
474 else if constexpr (std::is_same_v<unwrapped_type, double>)
475 return as_floating_point();
476 else if constexpr (std::is_same_v<unwrapped_type, bool>)
478 else if constexpr (std::is_same_v<unwrapped_type, date>)
480 else if constexpr (std::is_same_v<unwrapped_type, time>)
482 else if constexpr (std::is_same_v<unwrapped_type, date_time>)
483 return as_date_time();
503 template <
typename T>
505 optional<T> value_exact()
const noexcept(impl::value_retrieval_is_nothrow<T>);
633 template <
typename T>
635 optional<T> value()
const noexcept(impl::value_retrieval_is_nothrow<T>);
654 template <
typename T>
656 auto value_or(T&& default_value)
const noexcept(impl::value_retrieval_is_nothrow<T>);
686 template <
typename T>
688 decltype(
auto) ref() &
noexcept
690 return do_ref<T>(*
this);
694 template <
typename T>
696 decltype(
auto) ref() &&
noexcept
698 return do_ref<T>(std::move(*
this));
702 template <
typename T>
704 decltype(
auto) ref()
const&
noexcept
706 return do_ref<T>(*
this);
710 template <
typename T>
712 decltype(
auto) ref()
const&&
noexcept
714 return do_ref<T>(std::move(*
this));
734 template <
typename Func,
typename Node,
typename T>
735 static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, Node>>;
737 template <
typename Func,
typename Node,
typename T>
738 static constexpr bool can_visit_nothrow = std::is_nothrow_invocable_v<Func, ref_cast_type<T, Node>>;
740 template <
typename Func,
typename Node>
741 static constexpr bool can_visit_any = can_visit<Func, Node, table>
742 || can_visit<Func, Node, array>
743 || can_visit<Func, Node, std::string>
744 || can_visit<Func, Node, int64_t>
745 || can_visit<Func, Node, double>
746 || can_visit<Func, Node, bool>
747 || can_visit<Func, Node, date>
748 || can_visit<Func, Node, time>
749 || can_visit<Func, Node, date_time>;
753 template <
typename Func,
typename Node>
754 static constexpr bool can_visit_all = can_visit<Func, Node, table>
755 && can_visit<Func, Node, array>
756 && can_visit<Func, Node, std::string>
757 && can_visit<Func, Node, int64_t>
758 && can_visit<Func, Node, double>
759 && can_visit<Func, Node, bool>
760 && can_visit<Func, Node, date>
761 && can_visit<Func, Node, time>
762 && can_visit<Func, Node, date_time>;
764 template <
typename Func,
typename Node,
typename T>
765 static constexpr bool visit_is_nothrow_one = !can_visit<Func, Node, T> || can_visit_nothrow<Func, Node, T>;
767 template <
typename Func,
typename Node>
768 static constexpr bool visit_is_nothrow = visit_is_nothrow_one<Func, Node, table>
769 && visit_is_nothrow_one<Func, Node, array>
770 && visit_is_nothrow_one<Func, Node, std::string>
771 && visit_is_nothrow_one<Func, Node, int64_t>
772 && visit_is_nothrow_one<Func, Node, double>
773 && visit_is_nothrow_one<Func, Node, bool>
774 && visit_is_nothrow_one<Func, Node, date>
775 && visit_is_nothrow_one<Func, Node, time>
776 && visit_is_nothrow_one<Func, Node, date_time>;
780 template <
typename Func,
typename Node,
typename T,
bool = can_visit<Func, Node, T>>
781 struct visit_return_type_
783 using type =
decltype(std::declval<Func>()(std::declval<ref_cast_type<T, Node>>()));
785 template <
typename Func,
typename Node,
typename T>
786 struct visit_return_type_<Func, Node, T, false>
791 template <
typename Func,
typename Node,
typename T>
792 using visit_return_type =
typename visit_return_type_<Func, Node, T>::type;
794 template <
typename A,
typename B>
795 using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>;
797 template <
typename Func,
typename Node>
798 static decltype(
auto) do_visit(Func&& visitor, Node&& n)
noexcept(visit_is_nothrow<Func&&, Node&&>)
800 static_assert(can_visit_any<Func&&, Node&&>,
801 "TOML node visitors must be invocable for at least one of the toml::node "
802 "specializations:" TOML_SA_NODE_TYPE_LIST);
806 case node_type::table:
807 if constexpr (can_visit<Func&&, Node&&, table>)
808 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<table>());
811 case node_type::array:
812 if constexpr (can_visit<Func&&, Node&&, array>)
813 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<array>());
816 case node_type::string:
817 if constexpr (can_visit<Func&&, Node&&, std::string>)
818 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<std::string>());
821 case node_type::integer:
822 if constexpr (can_visit<Func&&, Node&&, int64_t>)
823 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<int64_t>());
826 case node_type::floating_point:
827 if constexpr (can_visit<Func&&, Node&&, double>)
828 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<double>());
831 case node_type::boolean:
832 if constexpr (can_visit<Func&&, Node&&, bool>)
833 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<bool>());
836 case node_type::date:
837 if constexpr (can_visit<Func&&, Node&&, date>)
838 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<date>());
841 case node_type::time:
842 if constexpr (can_visit<Func&&, Node&&, time>)
843 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<time>());
846 case node_type::date_time:
847 if constexpr (can_visit<Func&&, Node&&, date_time>)
848 return static_cast<Func&&
>(visitor)(
static_cast<Node&&
>(n).
template ref_cast<date_time>());
855 if constexpr (!can_visit_all<Func&&, Node&&>)
860 nonvoid<visit_return_type<Func&&, Node&&, table>,
861 nonvoid<visit_return_type<Func&&, Node&&, array>,
862 nonvoid<visit_return_type<Func&&, Node&&, std::string>,
863 nonvoid<visit_return_type<Func&&, Node&&, int64_t>,
864 nonvoid<visit_return_type<Func&&, Node&&, double>,
865 nonvoid<visit_return_type<Func&&, Node&&, bool>,
866 nonvoid<visit_return_type<Func&&, Node&&, date>,
867 nonvoid<visit_return_type<Func&&, Node&&, time>,
868 visit_return_type<Func&&, Node&&, date_time>
873 if constexpr (!std::is_void_v<return_type>)
875 static_assert(std::is_default_constructible_v<return_type>,
876 "Non-exhaustive visitors must return a default-constructible type, or void");
877 return return_type{};
919 template <
typename Func>
920 decltype(
auto) visit(Func&& visitor) &
noexcept(visit_is_nothrow<Func&&, node&>)
922 return do_visit(
static_cast<Func&&
>(visitor), *
this);
926 template <
typename Func>
927 decltype(
auto) visit(Func&& visitor) &&
noexcept(visit_is_nothrow<Func&&, node&&>)
929 return do_visit(
static_cast<Func&&
>(visitor),
static_cast<node&&
>(*
this));
933 template <
typename Func>
934 decltype(
auto) visit(Func&& visitor)
const&
noexcept(visit_is_nothrow<Func&&, const node&>)
936 return do_visit(
static_cast<Func&&
>(visitor), *
this);
940 template <
typename Func>
941 decltype(
auto) visit(Func&& visitor)
const&&
noexcept(visit_is_nothrow<Func&&, const node&&>)
943 return do_visit(
static_cast<Func&&
>(visitor),
static_cast<const node&&
>(*
this));
953 explicit operator node_view<node>()
noexcept;
957 explicit operator node_view<const node>()
const noexcept;
998 node_view<node>
at_path(std::string_view
path)
noexcept;
1005 node_view<const node>
at_path(std::string_view
path)
const noexcept;
1047 node_view<node>
at_path(
const toml::path&
path)
noexcept;
1054 node_view<const node>
at_path(
const toml::path&
path)
const noexcept;
1056#if TOML_ENABLE_WINDOWS_COMPAT
1074 node_view<const node>
at_path(std::wstring_view
path)
const;
1087 node_view<node> operator[](
const toml::path&
path)
noexcept;
1098 node_view<const node> operator[](
const toml::path&
path)
const noexcept;