fix string constructor range version

This commit is contained in:
bolero-MURAKAMI 2013-09-05 22:52:42 +09:00
parent e179cefdac
commit 330e708eff
3 changed files with 136 additions and 36 deletions

View file

@ -74,6 +74,10 @@ namespace testspr {
SPROUT_STATIC_CONSTEXPR auto s1 = sprout::string_t<10>::type(cstr, cstr + 6);
TESTSPR_BOTH_ASSERT(s1 == "foobar");
}
{
SPROUT_STATIC_CONSTEXPR auto s1 = sprout::string_t<10>::type(testspr::reduct_input(str1.begin()), testspr::reduct_input(str1.begin() + 6));
TESTSPR_BOTH_ASSERT(s1 == "foobar");
}
{
auto s1 = sprout::string_t<10>::type({'f', 'o', 'o', 'b', 'a', 'r'});
TESTSPR_ASSERT(s1 == "foobar");

View file

@ -155,36 +155,36 @@ namespace sprout {
}
#endif
#if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION
template<typename ConstIterator>
static SPROUT_CONSTEXPR int compare(char_type const* s1, ConstIterator s2, std::size_t n) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR int compare(char_type const* s1, ConstInputIterator s2, std::size_t n) {
return sprout::tristate_lexicographical_compare(
sprout::ptr_index(s1), sprout::ptr_index(s1, n), char_type(),
s2, s2 + n, char_type(),
sprout::detail::char_traits_lt<char_traits>()
);
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR int compare(ConstIterator s1, char_type const* s2, std::size_t n) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR int compare(ConstInputIterator s1, char_type const* s2, std::size_t n) {
return sprout::tristate_lexicographical_compare(
s1, s1 + n, char_type(),
sprout::ptr_index(s2), sprout::ptr_index(s2, n), char_type(),
sprout::detail::char_traits_lt<char_traits>()
);
}
template<typename ConstIterator1, typename ConstIterator2>
static SPROUT_CONSTEXPR int compare(ConstIterator1 s1, ConstIterator2 s2, std::size_t n) {
template<typename ConstInputIterator1, typename ConstInputIterator2>
static SPROUT_CONSTEXPR int compare(ConstInputIterator1 s1, ConstInputIterator2 s2, std::size_t n) {
return sprout::tristate_lexicographical_compare(
s1, s1 + n, char_type(),
s2, s2 + n, char_type(),
sprout::detail::char_traits_lt<char_traits>()
);
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR std::size_t length(ConstIterator s) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR std::size_t length(ConstInputIterator s) {
return sprout::detail::strlen(s);
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR ConstInputIterator find(ConstInputIterator s, std::size_t n, char_type const& a) {
return sprout::ptr_unindex(
sprout::find_if(
s, s + n,
@ -192,18 +192,18 @@ namespace sprout {
)
);
}
template<typename Iterator, typename ConstIterator>
static Iterator move(Iterator s1, ConstIterator s2, std::size_t n) {
template<typename OutputIterator, typename ConstInputIterator>
static OutputIterator move(OutputIterator s1, ConstInputIterator s2, std::size_t n) {
std::copy_backward(s2, s2 + n, s1);
return s1;
}
template<typename Iterator, typename ConstIterator>
static Iterator copy(Iterator s1, ConstIterator s2, std::size_t n) {
template<typename OutputIterator, typename ConstInputIterator>
static OutputIterator copy(OutputIterator s1, ConstInputIterator s2, std::size_t n) {
std::copy(s2, s2 + n, s1);
return s1;
}
template<typename Iterator>
static Iterator assign(Iterator s, std::size_t n, char_type a) {
template<typename OutputIterator>
static OutputIterator assign(OutputIterator s, std::size_t n, char_type a) {
std::fill(s, s + n, a);
return s;
}
@ -238,19 +238,19 @@ namespace sprout {
return found != last;
}
#if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION
template<typename ConstIterator>
static SPROUT_CONSTEXPR std::size_t length(ConstIterator s, std::size_t n) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR std::size_t length(ConstInputIterator s, std::size_t n) {
return sprout::detail::strlen(s, n);
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR ConstInputIterator find(ConstInputIterator s, std::size_t n, char_type const& a) {
return sprout::find_if(
s, s + n,
sprout::bind2nd(sprout::detail::char_traits_eq<traits_type>(), a)
);
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR bool is_found(ConstIterator found, ConstIterator last) {
template<typename ConstInputIterator>
static SPROUT_CONSTEXPR bool is_found(ConstInputIterator found, ConstInputIterator last) {
return found != last;
}
#endif

View file

@ -11,6 +11,7 @@
#include <cstddef>
#include <string>
#include <algorithm>
#include <iterator>
#include <utility>
#include <stdexcept>
#include <type_traits>
@ -21,6 +22,7 @@
#include <sprout/array/make_array.hpp>
#include <sprout/iterator/reverse_iterator.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
#include <sprout/algorithm/find.hpp>
#include <sprout/utility/forward.hpp>
#include <sprout/utility/swap.hpp>
@ -33,10 +35,76 @@
# include <sprout/iterator/index_iterator.hpp>
#endif
namespace sprout {
namespace detail {
template<typename Iterator, typename T, std::size_t N>
class constant_size_source {
private:
typedef sprout::array<T, N> array_type;
public:
typedef typename array_type::size_type size_type;
typedef typename array_type::const_reference const_reference;
private:
array_type arr_;
size_type size_;
public:
SPROUT_CONSTEXPR constant_size_source()
: arr_{{}}, size_()
{}
template<typename... Args>
explicit SPROUT_CONSTEXPR constant_size_source(size_type n, Args&&... args)
: arr_{{static_cast<T>(sprout::forward<Args>(args))...}}, size_(n)
{}
SPROUT_CONSTEXPR size_type size() const {
return size_;
}
SPROUT_CONSTEXPR const_reference operator[](size_type i) const {
return arr_[i];
}
};
template<typename T, std::size_t N, typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_random_access_iterator<RandomAccessIterator>::value,
typename std::iterator_traits<RandomAccessIterator>::difference_type
>::type
make_constant_size_source(RandomAccessIterator const& first, RandomAccessIterator const& last) {
return sprout::distance(first, last);
}
template<typename T, std::size_t N, typename InputIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
N == sizeof...(Args),
sprout::detail::constant_size_source<InputIterator, T, N>
>::type
make_constant_size_source_impl(InputIterator first, InputIterator last, Args const&... args) {
return sprout::detail::constant_size_source<InputIterator, T, N>(sizeof...(args) + (first != last ? 1 : 0), args...);
}
template<typename T, std::size_t N, typename InputIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
N != sizeof...(Args),
sprout::detail::constant_size_source<InputIterator, T, N>
>::type
make_constant_size_source_impl(InputIterator first, InputIterator last, Args const&... args) {
return first != last
? sprout::detail::make_constant_size_source_impl<T, N>(sprout::next(first), last, args..., *first)
: sprout::detail::constant_size_source<InputIterator, T, N>(sizeof...(args), args...)
;
}
template<typename T, std::size_t N, typename InputIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::is_random_access_iterator<InputIterator>::value,
sprout::detail::constant_size_source<InputIterator, T, N>
>::type
make_constant_size_source(InputIterator const& first, InputIterator const& last) {
return sprout::detail::make_constant_size_source_impl<T, N>(first, last);
}
} // namespace detail
namespace detail {
struct string_raw_construct_t {};
struct string_checked_construct_t {};
struct string_range_construct_t {};
template<typename T, std::size_t N, typename Traits = sprout::char_traits<T> >
class string_construct_access;
@ -44,13 +112,13 @@ namespace sprout {
template<typename T, std::size_t N, typename Traits>
class basic_string_impl {
public:
typedef T value_type;
typedef T& reference;
typedef T const& const_reference;
typedef typename Traits::char_type value_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef value_type* pointer;
typedef value_type const* const_pointer;
typedef Traits traits_type;
protected:
value_type elems[N + 1];
@ -67,7 +135,7 @@ namespace sprout {
String const& str, size_type pos, size_type n
)
: elems{
(sprout::math::less(Indexes, n) ? str[Indexes + pos]
(sprout::math::less(Indexes, n) ? static_cast<value_type>(str[Indexes + pos])
: value_type()
)...
}
@ -79,7 +147,7 @@ namespace sprout {
sprout::detail::string_checked_construct_t, String const& str, size_type pos, size_type n
)
: elems{
(sprout::math::less(Indexes, n) ? str[Indexes + pos]
(sprout::math::less(Indexes, n) ? static_cast<value_type>(str[Indexes + pos])
: value_type()
)...
}
@ -87,13 +155,43 @@ namespace sprout {
: throw std::out_of_range("basic_string<>: index out of range")
)
{}
template<typename RandomAccessIterator, typename Size, sprout::index_t... Indexes>
SPROUT_CONSTEXPR basic_string_impl(
sprout::index_tuple<Indexes...>,
sprout::detail::string_range_construct_t, RandomAccessIterator const& str, Size n,
std::random_access_iterator_tag*
)
: elems{
(sprout::math::less(Indexes, n) ? static_cast<value_type>(str[Indexes])
: value_type()
)...
}
, len(!(N < n) ? n
: throw std::out_of_range("basic_string<>: index out of range")
)
{}
template<typename InputIterator, typename Source, sprout::index_t... Indexes>
SPROUT_CONSTEXPR basic_string_impl(
sprout::index_tuple<Indexes...>,
sprout::detail::string_range_construct_t, InputIterator, Source const& str,
void*
)
: elems{
(sprout::math::less(Indexes, str.size()) ? static_cast<value_type>(str[Indexes])
: value_type()
)...
}
, len(!(N < str.size()) ? str.size()
: throw std::out_of_range("basic_string<>: index out of range")
)
{}
template<typename... Args, sprout::index_t... Indexes>
SPROUT_CONSTEXPR basic_string_impl(
sprout::index_tuple<Indexes...>,
sprout::detail::string_raw_construct_t, size_type n, Args&&... args
)
: elems{
(sprout::math::less(Indexes, n) ? sprout::forward<Args>(args)
(sprout::math::less(Indexes, n) ? static_cast<value_type>(sprout::forward<Args>(args))
: value_type()
)...
}
@ -231,14 +329,12 @@ namespace sprout {
sprout::detail::string_checked_construct_t(), s, 0, NS_SSCRISK_CEL_OR_SPROUT::min(n, traits_type::length(s))
)
{}
// !!!
// template<typename InputIterator>
// SPROUT_CONSTEXPR basic_string(InputIterator first, InputIterator last);
template<typename RandomAccessIterator>
SPROUT_CONSTEXPR basic_string(RandomAccessIterator first, RandomAccessIterator last)
template<typename InputIterator>
SPROUT_CONSTEXPR basic_string(InputIterator first, InputIterator last)
: impl_type(
sprout::make_index_tuple<N>::make(),
sprout::detail::string_checked_construct_t(), first, 0, sprout::distance(first, last)
sprout::detail::string_range_construct_t(), first, sprout::detail::make_constant_size_source<T, N>(first, last),
typename sprout::identity<typename std::iterator_traits<InputIterator>::iterator_category*>::type()
)
{}
basic_string(std::initializer_list<value_type> il)