mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-18 02:08:09 +08:00
@@ -9,27 +9,24 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_resize)
|
BOOST_AUTO_TEST_CASE(test_try_reserve)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
typedef std::vector<int> resizable_type;
|
// since BOOST_TEST is a macro, it cannot handle commas correctly.
|
||||||
typedef std::array<int,1> non_resizable_type;
|
// When toml::detail::has_reserve_method<std::array<int, 1>>::value
|
||||||
BOOST_TEST(toml::detail::has_resize_method<resizable_type>::value);
|
// is passed to a macro, C preprocessor considers
|
||||||
BOOST_TEST(!toml::detail::has_resize_method<non_resizable_type>::value);
|
// toml::detail::has_reserve_method<std::array<int as the first argument
|
||||||
|
// and 1>>::value as the second argument. We need an alias to avoid
|
||||||
|
// this problem.
|
||||||
|
using reservable_type = std::vector<int> ;
|
||||||
|
using nonreservable_type = std::array<int, 1>;
|
||||||
|
BOOST_TEST( toml::detail::has_reserve_method<reservable_type >::value);
|
||||||
|
BOOST_TEST(!toml::detail::has_reserve_method<nonreservable_type>::value);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<int> v;
|
std::vector<int> v;
|
||||||
toml::resize(v, 10);
|
toml::try_reserve(v, 100);
|
||||||
BOOST_TEST(v.size() == 10u);
|
BOOST_TEST(v.capacity() == 100u);
|
||||||
}
|
|
||||||
{
|
|
||||||
std::array<int, 15> a;
|
|
||||||
toml::resize(a, 10);
|
|
||||||
BOOST_TEST(a.size() == 15u);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::array<int, 15> a;
|
|
||||||
BOOST_CHECK_THROW(toml::resize(a, 20), std::invalid_argument);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
toml/get.hpp
55
toml/get.hpp
@@ -198,23 +198,23 @@ get(const basic_value<C, M, V>& v)
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// forward declaration to use this recursively. ignore this and go ahead.
|
// forward declaration to use this recursively. ignore this and go ahead.
|
||||||
|
|
||||||
// array-like type with resize(N) method
|
// array-like type with push_back(value) method
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
detail::enable_if_t<detail::conjunction<
|
detail::enable_if_t<detail::conjunction<
|
||||||
detail::is_container<T>, // T is container
|
detail::is_container<T>, // T is a container
|
||||||
detail::has_resize_method<T>, // T::resize(N) works
|
detail::has_push_back_method<T>, // T::push_back(value) works
|
||||||
detail::negation< // but not toml::array
|
detail::negation< // but not toml::array
|
||||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||||
>::value, T>
|
>::value, T>
|
||||||
get(const basic_value<C, M, V>&);
|
get(const basic_value<C, M, V>&);
|
||||||
|
|
||||||
// array-like type with resize(N) method
|
// array-like type without push_back(value) method
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
detail::enable_if_t<detail::conjunction<
|
detail::enable_if_t<detail::conjunction<
|
||||||
detail::is_container<T>, // T is container
|
detail::is_container<T>, // T is a container
|
||||||
detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
|
detail::negation<detail::has_push_back_method<T>>, // w/o push_back(...)
|
||||||
detail::negation< // not toml::array
|
detail::negation< // not toml::array
|
||||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||||
>::value, T>
|
>::value, T>
|
||||||
@@ -274,31 +274,54 @@ get(const basic_value<C, M, V>&);
|
|||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
detail::enable_if_t<detail::conjunction<
|
detail::enable_if_t<detail::conjunction<
|
||||||
detail::is_container<T>, // T is container
|
detail::is_container<T>, // T is a container
|
||||||
detail::has_resize_method<T>, // T::resize(N) works
|
detail::has_push_back_method<T>, // container.push_back(elem) works
|
||||||
detail::negation< // but not toml::array
|
detail::negation< // but not toml::array
|
||||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||||
>::value, T>
|
>::value, T>
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
using value_type = typename T::value_type;
|
using value_type = typename T::value_type;
|
||||||
const auto& ar = v.as_array();
|
const auto& ary = v.as_array();
|
||||||
|
|
||||||
T container;
|
T container;
|
||||||
container.resize(ar.size());
|
try_reserve(container, ary.size());
|
||||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
|
||||||
[](const value& x){return ::toml::get<value_type>(x);});
|
for(const auto& elem : ary)
|
||||||
|
{
|
||||||
|
container.push_back(get<value_type>(elem));
|
||||||
|
}
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// array-like types; but does not have resize(); most likely std::array.
|
// std::forward_list does not have push_back, insert, or emplace.
|
||||||
|
// It has insert_after, emplace_after, push_front.
|
||||||
|
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
detail::enable_if_t<detail::is_std_forward_list<T>::value, T>
|
||||||
|
get(const basic_value<C, M, V>& v)
|
||||||
|
{
|
||||||
|
using value_type = typename T::value_type;
|
||||||
|
T container;
|
||||||
|
for(const auto& elem : v.as_array())
|
||||||
|
{
|
||||||
|
container.push_front(get<value_type>(elem));
|
||||||
|
}
|
||||||
|
container.reverse();
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// array-like types, without push_back(). most likely [std|boost]::array.
|
||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
detail::enable_if_t<detail::conjunction<
|
detail::enable_if_t<detail::conjunction<
|
||||||
detail::is_container<T>, // T is container
|
detail::is_container<T>, // T is a container
|
||||||
detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
|
detail::negation<detail::has_push_back_method<T>>, // w/o push_back
|
||||||
detail::negation< // but not toml::array
|
detail::negation< // T is not toml::array
|
||||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||||
>::value, T>
|
>::value, T>
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <forward_list>
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
#if __has_include(<string_view>)
|
#if __has_include(<string_view>)
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@@ -43,17 +44,23 @@ struct has_mapped_type_impl
|
|||||||
template<typename T> static std::true_type check(typename T::mapped_type*);
|
template<typename T> static std::true_type check(typename T::mapped_type*);
|
||||||
template<typename T> static std::false_type check(...);
|
template<typename T> static std::false_type check(...);
|
||||||
};
|
};
|
||||||
struct has_resize_method_impl
|
struct has_reserve_method_impl
|
||||||
{
|
{
|
||||||
constexpr static std::size_t dummy=0;
|
|
||||||
template<typename T> static std::true_type check(decltype(std::declval<T>().resize(dummy))*);
|
|
||||||
template<typename T> static std::false_type check(...);
|
template<typename T> static std::false_type check(...);
|
||||||
|
template<typename T> static std::true_type check(
|
||||||
|
decltype(std::declval<T>().reserve(std::declval<std::size_t>()))*);
|
||||||
|
};
|
||||||
|
struct has_push_back_method_impl
|
||||||
|
{
|
||||||
|
template<typename T> static std::false_type check(...);
|
||||||
|
template<typename T> static std::true_type check(
|
||||||
|
decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))*);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct is_comparable_impl
|
struct is_comparable_impl
|
||||||
{
|
{
|
||||||
template<typename T> static std::true_type check(decltype(std::declval<T>() < std::declval<T>())*);
|
|
||||||
template<typename T> static std::false_type check(...);
|
template<typename T> static std::false_type check(...);
|
||||||
|
template<typename T> static std::true_type check(
|
||||||
|
decltype(std::declval<T>() < std::declval<T>())*);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct has_from_toml_method_impl
|
struct has_from_toml_method_impl
|
||||||
@@ -91,7 +98,9 @@ struct has_key_type : decltype(has_key_type_impl::check<T>(nullptr)){};
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
|
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
struct has_reserve_method : decltype(has_reserve_method_impl::check<T>(nullptr)){};
|
||||||
|
template<typename T>
|
||||||
|
struct has_push_back_method : decltype(has_push_back_method_impl::check<T>(nullptr)){};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
|
struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
|
||||||
|
|
||||||
@@ -149,6 +158,10 @@ template<typename T> struct is_std_tuple : std::false_type{};
|
|||||||
template<typename ... Ts>
|
template<typename ... Ts>
|
||||||
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
|
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
|
||||||
|
|
||||||
|
template<typename T> struct is_std_forward_list : std::false_type{};
|
||||||
|
template<typename T>
|
||||||
|
struct is_std_forward_list<std::forward_list<T>> : std::true_type{};
|
||||||
|
|
||||||
template<typename T> struct is_chrono_duration: std::false_type{};
|
template<typename T> struct is_chrono_duration: std::false_type{};
|
||||||
template<typename Rep, typename Period>
|
template<typename Rep, typename Period>
|
||||||
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||||
|
@@ -36,30 +36,25 @@ inline std::unique_ptr<T> make_unique(Ts&& ... args)
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
template<typename Container>
|
||||||
template<typename T>
|
void try_reserve_impl(Container& container, std::size_t N, std::true_type)
|
||||||
inline void resize_impl(T& container, std::size_t N, std::true_type)
|
|
||||||
{
|
{
|
||||||
container.resize(N);
|
container.reserve(N);
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
template<typename Container>
|
||||||
template<typename T>
|
void try_reserve_impl(Container&, std::size_t, std::false_type) noexcept
|
||||||
inline void resize_impl(T& container, std::size_t N, std::false_type)
|
|
||||||
{
|
{
|
||||||
if(container.size() >= N) {return;}
|
return;
|
||||||
|
|
||||||
throw std::invalid_argument("not resizable type");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
template<typename T>
|
template<typename Container>
|
||||||
inline void resize(T& container, std::size_t N)
|
void try_reserve(Container& container, std::size_t N)
|
||||||
{
|
{
|
||||||
if(container.size() == N) {return;}
|
if(N <= container.size()) {return;}
|
||||||
|
detail::try_reserve_impl(container, N, detail::has_reserve_method<Container>{});
|
||||||
return detail::resize_impl(container, N, detail::has_resize_method<T>());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
Reference in New Issue
Block a user