From ba3d41d913e973a82b3b6b59a6262e521099f694 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Wed, 14 Apr 2021 11:21:48 +0900 Subject: [PATCH] feat(#156): add find_or(value, keys..., opt) --- toml/get.hpp | 18 +++++++++++++++ toml/utility.hpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/toml/get.hpp b/toml/get.hpp index 5095caf..f941a75 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -1033,6 +1033,24 @@ find_or(const basic_value& v, const toml::key& ky, T&& opt) return get_or(tab.at(ky), std::forward(opt)); } +template class M, template class V, + typename ... Ks> +auto find_or(const basic_value& v, const toml::key& ky, Ks&& ... keys) + -> decltype(find_or(v, ky, detail::last_one(std::forward(keys)...))) +{ + if(!v.is_table()) + { + return detail::last_one(std::forward(keys)...); + } + const auto& tab = v.as_table(); + if(tab.count(ky) == 0) + { + return detail::last_one(std::forward(keys)...); + } + return find_or(tab.at(ky), std::forward(keys)...); +} + // ============================================================================ // expect diff --git a/toml/utility.hpp b/toml/utility.hpp index 113bec6..96e53db 100644 --- a/toml/utility.hpp +++ b/toml/utility.hpp @@ -89,5 +89,64 @@ T from_string(const std::string& str, T opt) return v; } +namespace detail +{ +#if __cplusplus >= 201402L +template +decltype(auto) last_one(T&& tail) noexcept +{ + return std::forward(tail); +} + +template +decltype(auto) last_one(T&& /*head*/, Ts&& ... tail) noexcept +{ + return last_one(std::forward(tail)...); +} +#else // C++11 +// The following code +// ```cpp +// 1 | template +// 2 | auto last_one(T&& /*head*/, Ts&& ... tail) +// 3 | -> decltype(last_one(std::forward(tail)...)) +// 4 | { +// 5 | return last_one(std::forward(tail)...); +// 6 | } +// ``` +// does not work because the function `last_one(...)` is not yet defined at +// line #3, so `decltype()` cannot deduce the type returned from `last_one`. +// So we need to determine return type in a different way, like a meta func. + +template +struct last_one_in_pack; +template +struct last_one_in_pack +{ + using type = typename last_one_in_pack::type; +}; +template +struct last_one_in_pack +{ + using type = T; +}; +template +using last_one_in_pack_t = typename last_one_in_pack::type; + +template +T&& last_one(T&& tail) noexcept +{ + return std::forward(tail); +} + +template +last_one_in_pack_t +last_one(T&& /*head*/, Ts&& ... tail) +{ + return last_one(std::forward(tail)...); +} + +#endif +} // detail + }// toml #endif // TOML11_UTILITY