From 3adba237b89835d2e200b26137608eff4f2fa6da Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 18 Mar 2019 16:28:27 +0900 Subject: [PATCH 1/5] feat: enable to show message for deprecated() --- toml/utility.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/toml/utility.hpp b/toml/utility.hpp index 01fe6d7..238a87d 100644 --- a/toml/utility.hpp +++ b/toml/utility.hpp @@ -8,11 +8,11 @@ #include #if __cplusplus >= 201402L -# define TOML11_MARK_AS_DEPRECATED [[deprecated]] +# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]] #elif defined(__GNUC__) -# define TOML11_MARK_AS_DEPRECATED __attribute__((deprecated)) +# define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg))) #elif defined(_MSC_VER) -# define TOML11_MARK_AS_DEPRECATED __declspec(deprecated) +# define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg)) #else # define TOML11_MARK_AS_DEPRECATED #endif From 4a58b629ce48679bdec9dd1c2ee8c40e865dc6d4 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 18 Mar 2019 16:30:41 +0900 Subject: [PATCH 2/5] feat: add a way to check arg is "string literal" --- toml/traits.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/toml/traits.hpp b/toml/traits.hpp index 7f8f413..7f5654b 100644 --- a/toml/traits.hpp +++ b/toml/traits.hpp @@ -169,6 +169,21 @@ using return_type_of_t = typename std::result_of::type; #endif +// --------------------------------------------------------------------------- +// is_string_literal +// +// to use this, pass `typename remove_reference::type` to T. + +template +struct is_string_literal: +disjunction< + std::is_same, + conjunction< + std::is_array, + std::is_same::type> + > + >{}; + }// detail }//toml #endif // TOML_TRAITS From ca3f6102efe2c23636bd1d0a6f913cf0e0f92e7c Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 18 Mar 2019 16:44:36 +0900 Subject: [PATCH 3/5] fix: correctly resolve overloads of get_or --- tests/test_get_related_func.cpp | 59 ++++++++++++- toml/get.hpp | 148 +++++++++++++++++++++++++++----- 2 files changed, 185 insertions(+), 22 deletions(-) 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) From aade704411e41e19c9a4c80443916126c775daa9 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 18 Mar 2019 17:10:18 +0900 Subject: [PATCH 4/5] refactor: remove needless overload of get_or --- toml/get.hpp | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/toml/get.hpp b/toml/get.hpp index e3bbffc..4e79783 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -545,40 +545,6 @@ T get_or(const toml::value& v, T&& opt) 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) From 7a0ecf977d4eeaf552c930acd84a74a768464cff Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 18 Mar 2019 17:44:03 +0900 Subject: [PATCH 5/5] feat: add find_or(table, key, fallback) get_or(value, fallback) is still ok, but get_or(table, key, fallback) is now deprecated. --- tests/test_get_related_func.cpp | 146 ++++++++++++++++++++--- toml/get.hpp | 199 ++++++++++++++++++++++++++++++-- 2 files changed, 322 insertions(+), 23 deletions(-) diff --git a/tests/test_get_related_func.cpp b/tests/test_get_related_func.cpp index 8ba61c6..30eb362 100644 --- a/tests/test_get_related_func.cpp +++ b/tests/test_get_related_func.cpp @@ -45,18 +45,6 @@ BOOST_AUTO_TEST_CASE(test_find) BOOST_AUTO_TEST_CASE(test_get_or) { - { - toml::table v{{"num", 42}}; - BOOST_CHECK_EQUAL(42, toml::get_or(v, "num", 0)); - BOOST_CHECK_EQUAL(0, toml::get_or(v, "foo", 0)); - } - { - toml::value v = toml::table{{"num", 42}}; - 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); @@ -69,8 +57,10 @@ BOOST_AUTO_TEST_CASE(test_get_or) { 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::integer opt(0); + BOOST_CHECK_EQUAL(42, toml::get_or(v1, opt)); + BOOST_CHECK_EQUAL(0, toml::get_or(v2, opt)); toml::value v3("foobar"); toml::string s("bazqux"); @@ -118,6 +108,134 @@ BOOST_AUTO_TEST_CASE(test_get_or) } } +BOOST_AUTO_TEST_CASE(test_find_or) +{ + // ======================================================================== + // pass toml::value + // + // requires conversion int -> uint + { + toml::table v{{"num", 42}}; + BOOST_CHECK_EQUAL(42u, toml::find_or(v, "num", 0u)); + BOOST_CHECK_EQUAL(0u, toml::find_or(v, "foo", 0u)); + } + // exact toml type + { + toml::table v1{{"key", 42 }}; + toml::table v2{{"key", 3.14}}; + toml::table v3{{"not", "key"}}; + + toml::integer opt(0); + BOOST_CHECK_EQUAL(42, toml::find_or(v1, "key", opt)); + BOOST_CHECK_EQUAL(0, toml::find_or(v2, "key", opt)); + BOOST_CHECK_EQUAL(0, toml::find_or(v3, "key", opt)); + + toml::table v4{{"str", "foobar"}}; + toml::string s("bazqux"); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v4, "str", s)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v1, "str", s)); + } + // std::string + { + toml::table v1{{"key", "foobar"}}; + toml::table v2{{"key", 42}}; + + std::string s1("bazqux"); + const std::string s2("bazqux"); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s1)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s1)); + + std::string& v1r = toml::find_or(v1, "key", s1); + std::string& s1r = toml::find_or(v2, "key", s1); + + BOOST_CHECK_EQUAL("foobar", v1r); + BOOST_CHECK_EQUAL("bazqux", s1r); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s2)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s2)); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(std::move(v1), "key", std::move(s1))); + s1 = "bazqux"; // restoring moved value + BOOST_CHECK_EQUAL("bazqux", toml::find_or(std::move(v2), "key", std::move(s1))); + } + // string literal + { + toml::table v1{{"key", "foobar"}}; + toml::table v2{{"key",42}}; + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", "bazqux")); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", "bazqux")); + + const char* lit = "bazqux"; + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", lit)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", lit)); + } + + // ======================================================================== + // pass toml::value + // + // requires conversion int -> uint + { + toml::table v = toml::table{{"num", 42}}; + BOOST_CHECK_EQUAL(42u, toml::find_or(v, "num", 0u)); + BOOST_CHECK_EQUAL(0u, toml::find_or(v, "foo", 0u)); + } + // exact toml type + { + toml::value v1 = toml::table{{"key", 42 }}; + toml::value v2 = toml::table{{"key", 3.14}}; + toml::value v3 = toml::table{{"not", "key"}}; + + BOOST_CHECK_EQUAL(42, toml::find_or(v1, "key", toml::integer(0))); + BOOST_CHECK_EQUAL( 0, toml::find_or(v2, "key", toml::integer(0))); + BOOST_CHECK_EQUAL( 0, toml::find_or(v3, "key", toml::integer(0))); + + toml::value v4 = toml::table{{"str", "foobar"}}; + toml::string s("bazqux"); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v4, "str", s)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v1, "str", s)); + } + // std::string + { + toml::value v1 = toml::table{{"key", "foobar"}}; + toml::value v2 = toml::table{{"key", 42}}; + + std::string s1("bazqux"); + const std::string s2("bazqux"); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s1)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s1)); + + std::string& v1r = toml::find_or(v1, "key", s1); + std::string& s1r = toml::find_or(v2, "key", s1); + + BOOST_CHECK_EQUAL("foobar", v1r); + BOOST_CHECK_EQUAL("bazqux", s1r); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s2)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s2)); + + BOOST_CHECK_EQUAL("foobar", toml::find_or(std::move(v1), "key", std::move(s1))); + s1 = "bazqux"; // restoring moved value + BOOST_CHECK_EQUAL("bazqux", toml::find_or(std::move(v2), "key", std::move(s1))); + } + // string literal + { + toml::value v1 = toml::table{{"key", "foobar"}}; + toml::value v2 = toml::table{{"key",42}}; + + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", "bazqux")); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", "bazqux")); + + const char* lit = "bazqux"; + BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", lit)); + BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", lit)); + } +} + BOOST_AUTO_TEST_CASE(test_expect) { { diff --git a/toml/get.hpp b/toml/get.hpp index 4e79783..ed211b0 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -546,56 +546,237 @@ T get_or(const toml::value& v, T&& opt) } } +// =========================================================================== +// get_or(table, key, fallback) +// +// DEPRECATED: use find_or instead. + template +TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.") auto get_or(const toml::table& tab, const toml::key& ky, T&& opt) -> decltype(get_or(std::declval(), std::forward(opt))) { - if(tab.count(ky) == 0) {return std::forward(opt);} + if(tab.count(ky) == 0) {return opt;} return ::toml::get_or(tab.at(ky), std::forward(opt)); } template +TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.") auto get_or(toml::table& tab, const toml::key& ky, T&& opt) -> decltype(get_or(std::declval(), std::forward(opt))) { - if(tab.count(ky) == 0) {return std::forward(opt);} + if(tab.count(ky) == 0) {return opt;} return ::toml::get_or(tab[ky], std::forward(opt)); } template +TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.") auto get_or(toml::table&& tab, const toml::key& ky, T&& opt) -> decltype(get_or(std::declval(), std::forward(opt))) { - if(tab.count(ky) == 0) {return std::forward(opt);} + if(tab.count(ky) == 0) {return opt;} return ::toml::get_or(std::move(tab[ky]), std::forward(opt)); } template +TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.") auto get_or(const toml::value& v, const toml::key& ky, T&& opt) -> decltype(get_or(std::declval(), std::forward(opt))) { - if(v.type() != toml::value_t::Table){return std::forward(opt);} + if(!v.is_table()) {return opt;} const auto& tab = toml::get(v); - if(tab.count(ky) == 0) {return std::forward(opt);} + if(tab.count(ky) == 0) {return opt;} return ::toml::get_or(tab.at(ky), std::forward(opt)); } template +TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.") auto get_or(toml::value& v, const toml::key& ky, T&& opt) -> decltype(get_or(std::declval(), std::forward(opt))) { - if(v.type() != toml::value_t::Table){return std::forward(opt);} + if(!v.is_table()) {return opt;} auto& tab = toml::get(v); - if(tab.count(ky) == 0) {return std::forward(opt);} + if(tab.count(ky) == 0) {return opt;} return ::toml::get_or(tab[ky], std::forward(opt)); } template +TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.") auto get_or(toml::value&& v, const toml::key& ky, T&& opt) -> decltype(get_or(std::declval(), std::forward(opt))) { - if(v.type() != toml::value_t::Table){return std::forward(opt);} + if(!v.is_table()) {return opt;} auto tab = toml::get(std::move(v)); - if(tab.count(ky) == 0) {return std::forward(opt);} + if(tab.count(ky) == 0) {return opt;} return ::toml::get_or(std::move(tab[ky]), std::forward(opt)); } +// =========================================================================== +// find_or(value, key, fallback) + +// --------------------------------------------------------------------------- +// exact types (return type can be a reference) +template::value, std::nullptr_t>::type = nullptr> +T const& find_or(const toml::value& v, const toml::key& ky, const T& opt) +{ + if(!v.is_table()) {return opt;} + const auto& tab = toml::get(v); + if(tab.count(ky) == 0) {return opt;} + return get_or(tab.at(ky), opt); +} + +template::value, std::nullptr_t>::type = nullptr> +T& find_or(toml::value& v, const toml::key& ky, T& opt) +{ + if(!v.is_table()) {return opt;} + auto& tab = toml::get(v); + if(tab.count(ky) == 0) {return opt;} + return get_or(tab[ky], opt); +} + +template::value, std::nullptr_t>::type = nullptr> +T&& find_or(toml::value&& v, const toml::key& ky, T&& opt) +{ + if(!v.is_table()) {return opt;} + auto tab = toml::get(std::move(v)); + if(tab.count(ky) == 0) {return opt;} + return get_or(std::move(tab[ky]), std::forward(opt)); +} + +// --------------------------------------------------------------------------- +// std::string (return type can be a reference) +template::value, std::nullptr_t>::type = nullptr> +std::string const& find_or(const toml::value& v, const toml::key& ky, const T& opt) +{ + if(!v.is_table()) {return opt;} + const auto& tab = toml::get(v); + if(tab.count(ky) == 0) {return opt;} + return get_or(tab.at(ky), opt); +} +template::value, std::nullptr_t>::type = nullptr> +std::string& find_or(toml::value& v, const toml::key& ky, T& opt) +{ + if(!v.is_table()) {return opt;} + auto& tab = toml::get(v); + if(tab.count(ky) == 0) {return opt;} + return get_or(tab[ky], opt); +} +template::value, std::nullptr_t>::type = nullptr> +std::string find_or(toml::value&& v, const toml::key& ky, T&& opt) +{ + if(!v.is_table()) {return opt;} + auto tab = toml::get(std::move(v)); + if(tab.count(ky) == 0) {return opt;} + return get_or(std::move(tab[ky]), std::forward(opt)); +} + +// --------------------------------------------------------------------------- +// string literal (deduced as std::string) +template::type>::value, + std::nullptr_t>::type = nullptr> +std::string find_or(const toml::value& v, const toml::key& ky, T&& opt) +{ + if(!v.is_table()) {return opt;} + const auto& tab = toml::get(v); + if(tab.count(ky) == 0) {return std::string(opt);} + return get_or(tab.at(ky), std::forward(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 find_or(const toml::value& v, const toml::key& ky, T&& opt) +{ + if(!v.is_table()) {return opt;} + const auto& tab = toml::get(v); + if(tab.count(ky) == 0) {return opt;} + return get_or(tab.at(ky), std::forward(opt)); +} + +// =========================================================================== +// find_or(table, key, opt) + +// --------------------------------------------------------------------------- +// exact types (return type can be a reference) +template::value, std::nullptr_t>::type = nullptr> +T const& find_or(const toml::table& tab, const toml::key& ky, const T& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(tab.at(ky), opt); +} + +template::value, std::nullptr_t>::type = nullptr> +T& find_or(toml::table& tab, const toml::key& ky, T& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(tab[ky], opt); +} + +template::value, std::nullptr_t>::type = nullptr> +T&& find_or(toml::table&& tab, const toml::key& ky, T&& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(std::move(tab[ky]), std::forward(opt)); +} + +// --------------------------------------------------------------------------- +// std::string (return type can be a reference) +template::value, std::nullptr_t>::type = nullptr> +std::string const& find_or(const toml::table& tab, const toml::key& ky, const T& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(tab.at(ky), opt); +} +template::value, std::nullptr_t>::type = nullptr> +std::string& find_or(toml::table& tab, const toml::key& ky, T& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(tab[ky], opt); +} +template::value, std::nullptr_t>::type = nullptr> +std::string find_or(toml::table&& tab, const toml::key& ky, T&& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(std::move(tab[ky]), std::forward(opt)); +} + +// --------------------------------------------------------------------------- +// string literal (deduced as std::string) +template::type>::value, + std::nullptr_t>::type = nullptr> +std::string find_or(const toml::table& tab, const toml::key& ky, T&& opt) +{ + if(tab.count(ky) == 0) {return std::string(opt);} + return get_or(tab.at(ky), std::forward(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 find_or(const toml::table& tab, const toml::key& ky, T&& opt) +{ + if(tab.count(ky) == 0) {return opt;} + return get_or(tab.at(ky), std::forward(opt)); +} + // ============================================================================ // expect