mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-17 00:38:08 +08:00
feat(#156): add find_or(value, keys..., opt)
This commit is contained in:
18
toml/get.hpp
18
toml/get.hpp
@@ -1033,6 +1033,24 @@ find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
|||||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
|
typename ... Ks>
|
||||||
|
auto find_or(const basic_value<C, M, V>& v, const toml::key& ky, Ks&& ... keys)
|
||||||
|
-> decltype(find_or<T>(v, ky, detail::last_one(std::forward<Ks>(keys)...)))
|
||||||
|
{
|
||||||
|
if(!v.is_table())
|
||||||
|
{
|
||||||
|
return detail::last_one(std::forward<Ks>(keys)...);
|
||||||
|
}
|
||||||
|
const auto& tab = v.as_table();
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
return detail::last_one(std::forward<Ks>(keys)...);
|
||||||
|
}
|
||||||
|
return find_or(tab.at(ky), std::forward<Ks>(keys)...);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// expect
|
// expect
|
||||||
|
|
||||||
|
@@ -89,5 +89,64 @@ T from_string(const std::string& str, T opt)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
template<typename T>
|
||||||
|
decltype(auto) last_one(T&& tail) noexcept
|
||||||
|
{
|
||||||
|
return std::forward<T>(tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename ... Ts>
|
||||||
|
decltype(auto) last_one(T&& /*head*/, Ts&& ... tail) noexcept
|
||||||
|
{
|
||||||
|
return last_one(std::forward<Ts>(tail)...);
|
||||||
|
}
|
||||||
|
#else // C++11
|
||||||
|
// The following code
|
||||||
|
// ```cpp
|
||||||
|
// 1 | template<typename T, typename ... Ts>
|
||||||
|
// 2 | auto last_one(T&& /*head*/, Ts&& ... tail)
|
||||||
|
// 3 | -> decltype(last_one(std::forward<Ts>(tail)...))
|
||||||
|
// 4 | {
|
||||||
|
// 5 | return last_one(std::forward<Ts>(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<typename ... Ts>
|
||||||
|
struct last_one_in_pack;
|
||||||
|
template<typename T, typename ... Ts>
|
||||||
|
struct last_one_in_pack<T, Ts...>
|
||||||
|
{
|
||||||
|
using type = typename last_one_in_pack<Ts...>::type;
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
struct last_one_in_pack<T>
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
template<typename ... Ts>
|
||||||
|
using last_one_in_pack_t = typename last_one_in_pack<Ts...>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T&& last_one(T&& tail) noexcept
|
||||||
|
{
|
||||||
|
return std::forward<T>(tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename ... Ts>
|
||||||
|
last_one_in_pack_t<Ts&& ...>
|
||||||
|
last_one(T&& /*head*/, Ts&& ... tail)
|
||||||
|
{
|
||||||
|
return last_one(std::forward<Ts>(tail)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
} // detail
|
||||||
|
|
||||||
}// toml
|
}// toml
|
||||||
#endif // TOML11_UTILITY
|
#endif // TOML11_UTILITY
|
||||||
|
Reference in New Issue
Block a user