diff --git a/tests/test_get_related_func.cpp b/tests/test_get_related_func.cpp index c47d8b6..8ba61c6 100644 --- a/tests/test_get_related_func.cpp +++ b/tests/test_get_related_func.cpp @@ -55,11 +55,66 @@ BOOST_AUTO_TEST_CASE(test_get_or) BOOST_CHECK_EQUAL(42, toml::get_or(v, "num", 0)); BOOST_CHECK_EQUAL(0, toml::get_or(v, "foo", 0)); } + + + // requires conversion int -> uint { toml::value v1(42); toml::value v2(3.14); - BOOST_CHECK_EQUAL(42, toml::get_or(v1, 0)); - BOOST_CHECK_EQUAL(0, toml::get_or(v2, 0)); + BOOST_CHECK_EQUAL(42u, toml::get_or(v1, 0u)); + BOOST_CHECK_EQUAL(0u, toml::get_or(v2, 0u)); + } + + // exact toml type + { + toml::value v1(42); + toml::value v2(3.14); + BOOST_CHECK_EQUAL(42, toml::get_or(v1, toml::integer(0))); + BOOST_CHECK_EQUAL(0, toml::get_or(v2, toml::integer(0))); + + toml::value v3("foobar"); + toml::string s("bazqux"); + + BOOST_CHECK_EQUAL("foobar", toml::get_or(v3, s)); + BOOST_CHECK_EQUAL("bazqux", toml::get_or(v1, s)); + + } + + // std::string + { + toml::value v1("foobar"); + toml::value v2(42); + + std::string s1("bazqux"); + const std::string s2("bazqux"); + + BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, s1)); + BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, s1)); + + std::string& v1r = toml::get_or(v1, s1); + std::string& s1r = toml::get_or(v2, s1); + + BOOST_CHECK_EQUAL("foobar", v1r); + BOOST_CHECK_EQUAL("bazqux", s1r); + + BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, s2)); + BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, s2)); + + BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, std::move(s1))); + BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, std::move(s1))); + } + + // string literal + { + toml::value v1("foobar"); + toml::value v2(42); + + BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, "bazqux")); + BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, "bazqux")); + + const char* lit = "bazqux"; + BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, lit)); + BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, lit)); } } diff --git a/toml/get.hpp b/toml/get.hpp index 6aad019..e3bbffc 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -420,13 +420,14 @@ find(toml::value&& v, const toml::key& ky) // ============================================================================ -// get_or +// get_or(value, fallback) -template -decltype(::toml::get::type>::type>( - std::declval())) -get_or(const toml::value& v, T&& opt) +// ---------------------------------------------------------------------------- +// specialization for the exact toml types (return type becomes lvalue ref) + +template::value, std::nullptr_t>::type = nullptr> +T const& get_or(const toml::value& v, const T& opt) { try { @@ -435,14 +436,12 @@ get_or(const toml::value& v, T&& opt) } catch(...) { - return std::forward(opt); + return opt; } } -template -decltype(::toml::get::type>::type>( - std::declval())) -get_or(toml::value& v, T&& opt) +template::value, std::nullptr_t>::type = nullptr> +T& get_or(toml::value& v, T& opt) { try { @@ -451,26 +450,135 @@ get_or(toml::value& v, T&& opt) } catch(...) { - return std::forward(opt); + return opt; } } -template -decltype(::toml::get::type>::type>( - std::declval())) -get_or(toml::value&& v, T&& opt) +template::value, std::nullptr_t>::type = nullptr> +T&& get_or(toml::value&& v, T&& opt) { try { return get::type>::type>(std::move(v)); + typename std::remove_reference::type>::type>(v); } catch(...) { - return std::forward(opt); + return opt; } } +// ---------------------------------------------------------------------------- +// specialization for std::string (return type becomes lvalue ref) + +template::value, std::nullptr_t>::type = nullptr> +std::string const& get_or(const toml::value& v, const T& opt) +{ + try + { + return get(v); + } + catch(...) + { + return opt; + } +} +template::value, std::nullptr_t>::type = nullptr> +std::string& get_or(toml::value& v, T& opt) +{ + try + { + return get(v); + } + catch(...) + { + return opt; + } +} +template::value, std::nullptr_t>::type = nullptr> +std::string get_or(toml::value&& v, T&& opt) +{ + try + { + return get(v); + } + catch(...) + { + return opt; + } +} +template::type>::value, + std::nullptr_t>::type = nullptr> +std::string get_or(const toml::value& v, T&& opt) +{ + try + { + return get(v); + } + catch(...) + { + return std::string(opt); + } +} + +// ---------------------------------------------------------------------------- +// others (require type conversion and return type cannot be lvalue reference) + +template>, + detail::negation>, + detail::negation::type>> + >::value, std::nullptr_t>::type = nullptr> +T get_or(const toml::value& v, T&& opt) +{ + try + { + return get::type>::type>(v); + } + catch(...) + { + return opt; + } +} +template>, + detail::negation>, + detail::negation::type>> + >::value, std::nullptr_t>::type = nullptr> +T get_or(toml::value& v, T&& opt) +{ + try + { + return get::type>::type>(v); + } + catch(...) + { + return opt; + } +} +template>, + detail::negation>, + detail::negation::type>> + >::value, std::nullptr_t>::type = nullptr> +T get_or(toml::value&& v, T&& opt) +{ + try + { + return get::type>::type>(v); + } + catch(...) + { + return opt; + } +} template auto get_or(const toml::table& tab, const toml::key& ky, T&& opt)