diff options
Diffstat (limited to 'src/toml11/toml/utility.hpp')
-rw-r--r-- | src/toml11/toml/utility.hpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/toml11/toml/utility.hpp b/src/toml11/toml/utility.hpp new file mode 100644 index 000000000..4a6b4309d --- /dev/null +++ b/src/toml11/toml/utility.hpp @@ -0,0 +1,149 @@ +// Copyright Toru Niina 2017. +// Distributed under the MIT License. +#ifndef TOML11_UTILITY_HPP +#define TOML11_UTILITY_HPP +#include <memory> +#include <sstream> +#include <utility> + +#include "traits.hpp" + +#if __cplusplus >= 201402L +# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]] +#elif defined(__GNUC__) +# define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg))) +#elif defined(_MSC_VER) +# define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg)) +#else +# define TOML11_MARK_AS_DEPRECATED +#endif + +namespace toml +{ + +#if __cplusplus >= 201402L + +using std::make_unique; + +#else + +template<typename T, typename ... Ts> +inline std::unique_ptr<T> make_unique(Ts&& ... args) +{ + return std::unique_ptr<T>(new T(std::forward<Ts>(args)...)); +} + +#endif // __cplusplus >= 2014 + +namespace detail +{ +template<typename Container> +void try_reserve_impl(Container& container, std::size_t N, std::true_type) +{ + container.reserve(N); + return; +} +template<typename Container> +void try_reserve_impl(Container&, std::size_t, std::false_type) noexcept +{ + return; +} +} // detail + +template<typename Container> +void try_reserve(Container& container, std::size_t N) +{ + if(N <= container.size()) {return;} + detail::try_reserve_impl(container, N, detail::has_reserve_method<Container>{}); + return; +} + +namespace detail +{ +inline std::string concat_to_string_impl(std::ostringstream& oss) +{ + return oss.str(); +} +template<typename T, typename ... Ts> +std::string concat_to_string_impl(std::ostringstream& oss, T&& head, Ts&& ... tail) +{ + oss << std::forward<T>(head); + return concat_to_string_impl(oss, std::forward<Ts>(tail) ... ); +} +} // detail + +template<typename ... Ts> +std::string concat_to_string(Ts&& ... args) +{ + std::ostringstream oss; + oss << std::boolalpha << std::fixed; + return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...); +} + +template<typename T> +T from_string(const std::string& str, T opt) +{ + T v(opt); + std::istringstream iss(str); + iss >> 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 T, typename ... Ts> +struct last_one_in_pack +{ + 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> +enable_if_t<(sizeof...(Ts) > 0), last_one_in_pack_t<Ts&& ...>> +last_one(T&& /*head*/, Ts&& ... tail) +{ + return last_one(std::forward<Ts>(tail)...); +} + +#endif +} // detail + +}// toml +#endif // TOML11_UTILITY |