rewrite sprout::algorithm::join performance

This commit is contained in:
bolero-MURAKAMI 2012-05-22 01:06:13 +09:00
parent 0ceabb5b9b
commit 1ea9d30e2a
145 changed files with 1359 additions and 364 deletions

View file

@ -5,7 +5,7 @@
#include <sprout/tuple/tuple.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/forward.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/shuffle.hpp>

View file

@ -6,7 +6,7 @@
#include <sprout/tuple/tuple.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/forward.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/shuffle.hpp>

View file

@ -6,7 +6,7 @@
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/copy.hpp>
#include <sprout/detail/container_complate.hpp>

View file

@ -5,7 +5,7 @@
#include <sprout/index_tuple.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
namespace sprout {

View file

@ -5,7 +5,7 @@
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/algorithm/fixed/swap_element.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT

View file

@ -4,7 +4,7 @@
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/swap_element.hpp>
#include <sprout/algorithm/fixed/pop_heap.hpp>

View file

@ -4,7 +4,7 @@
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/swap_element.hpp>
#include <sprout/algorithm/fixed/make_partial_heap.hpp>

View file

@ -4,7 +4,7 @@
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/swap_element.hpp>
#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT

View file

@ -4,7 +4,7 @@
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/fixed/result_of.hpp>
#include <sprout/algorithm/fixed/swap_element.hpp>
#include <sprout/algorithm/fixed/pop_heap.hpp>

View file

@ -3,6 +3,5 @@
#include <sprout/config.hpp>
#include <sprout/algorithm/string/join.hpp>
#include <sprout/algorithm/string/join2.hpp>
#endif // #ifndef SPROUT_ALGORITHM_STRING_HPP

View file

@ -1,22 +1,88 @@
#ifndef SPROUT_ALGORITHM_STRING_JOIN_HPP
#define SPROUT_ALGORITHM_STRING_JOIN_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/index_tuple.hpp>
#include <sprout/pit.hpp>
#include <sprout/iterator/traits.hpp>
#include <sprout/utility/enabler_if.hpp>
#include <sprout/range/adaptor/size_enumed.hpp>
#include <sprout/range/algorithm/lower_bound.hpp>
#include <sprout/range/numeric/partial_sum.hpp>
#include <sprout/weed/traits/type/is_c_str.hpp>
namespace sprout {
namespace algorithm {
namespace detail {
template<typename String, typename = void>
struct string_size;
template<typename String>
struct string_size<
String,
typename std::enable_if<sprout::weed::traits::is_c_str<String>::value>::type
>
: public std::integral_constant<
typename sprout::container_traits<String>::size_type,
sprout::container_traits<String>::static_size - 1
>
{};
template<typename String>
struct string_size<
String,
typename std::enable_if<!sprout::weed::traits::is_c_str<String>::value>::type
>
: public std::integral_constant<
typename sprout::container_traits<String>::size_type,
sprout::container_traits<String>::static_size
>
{};
template<
typename String,
typename sprout::enabler_if<sprout::weed::traits::is_c_str<String>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::container_traits<String>::difference_type
str_size(String const& str) {
return sprout::size(str) - 1;
}
template<
typename String,
typename sprout::enabler_if<!sprout::weed::traits::is_c_str<String>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::container_traits<String>::difference_type
str_size(String const& str) {
return sprout::size(str);
}
} // namespace detail
namespace result_of {
//
// join
//
template<typename ContainerContainer>
template<typename ContainerContainer, typename Separator = void>
struct join {
public:
typedef typename sprout::container_transform_traits<
typename sprout::container_traits<ContainerContainer>::value_type
>::template rebind_size<
sprout::container_traits<
typename sprout::container_traits<ContainerContainer>::value_type
>::static_size
? (sprout::container_traits<
typename sprout::container_traits<ContainerContainer>::value_type
>::static_size
+ sprout::algorithm::detail::string_size<Separator>::value
)
* sprout::container_traits<ContainerContainer>::static_size
- sprout::algorithm::detail::string_size<Separator>::value
: 0
>::type type;
};
template<typename ContainerContainer>
struct join<ContainerContainer, void> {
public:
typedef typename sprout::container_transform_traits<
typename sprout::container_traits<ContainerContainer>::value_type
@ -30,31 +96,80 @@ namespace sprout {
} // namespace result_of
namespace detail {
template<typename Result, typename ContainerInputIterator, typename... Args>
template<typename Result, typename ContIterator, typename SizeIterator, typename Sizes>
inline SPROUT_CONSTEXPR typename sprout::container_traits<Result>::value_type
join_impl_ra_2(
ContIterator first_cont,
SizeIterator found,
Sizes const& sizes,
sprout::index_t idx
)
{
typedef typename sprout::container_traits<Result>::value_type value_type;
return found == sizes.end() ? value_type()
: sprout::begin(first_cont[found - sizes.begin()])[idx - (found != sizes.begin() ? found[-1] : 0)]
;
}
template<typename Result, typename ContIterator, sprout::index_t... Indexes, typename Sizes>
inline SPROUT_CONSTEXPR Result
join_impl_ra_1(
ContIterator first_cont,
sprout::index_tuple<Indexes...>,
Sizes const& sizes
)
{
return sprout::make<Result>(
sprout::algorithm::detail::join_impl_ra_2<Result>(
first_cont,
sprout::range::lower_bound(sizes, Indexes + 1),
sizes,
Indexes
)...
);
}
template<typename Result, typename ContainerContainer>
inline SPROUT_CONSTEXPR Result
join_impl_ra(ContainerContainer const& cont_cont) {
typedef typename sprout::container_traits<Result>::difference_type size_type;
typedef sprout::array<
size_type,
sprout::container_traits<ContainerContainer>::static_size
> sizes_type;
return sprout::algorithm::detail::join_impl_ra_1<Result>(
sprout::begin(cont_cont),
sprout::index_range<0, sprout::container_traits<Result>::static_size>::make(),
sprout::range::partial_sum(
cont_cont | sprout::adaptors::size_enumed,
sprout::pit<sizes_type>()
)
);
}
template<typename Result, typename ContIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size == sizeof...(Args),
Result
>::type join_impl(
ContainerInputIterator first_cont,
ContainerInputIterator last_cont,
ContIterator first_cont,
ContIterator last_cont,
Args const&... args
);
template<typename Result, typename ContainerInputIterator, typename... Args>
template<typename Result, typename ContIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size != sizeof...(Args),
Result
>::type join_impl(
ContainerInputIterator first_cont,
ContainerInputIterator last_cont,
ContIterator first_cont,
ContIterator last_cont,
Args const&... args
);
template<typename Result, typename ContainerInputIterator, typename InputIterator, typename... Args>
template<typename Result, typename ContIterator, typename InputIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size == sizeof...(Args),
Result
>::type join_impl_1(
ContainerInputIterator first_cont,
ContainerInputIterator last_cont,
ContIterator first_cont,
ContIterator last_cont,
InputIterator first,
InputIterator last,
Args const&... args
@ -62,63 +177,344 @@ namespace sprout {
{
return sprout::make<Result>(args...);
}
template<typename Result, typename ContainerInputIterator, typename InputIterator, typename... Args>
template<typename Result, typename ContIterator, typename InputIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size != sizeof...(Args),
Result
>::type join_impl_1(
ContainerInputIterator first_cont,
ContainerInputIterator last_cont,
ContIterator first_cont,
ContIterator last_cont,
InputIterator first,
InputIterator last,
Args const&... args
)
{
return first != last
? sprout::algorithm::detail::join_impl_1<Result>(first_cont, last_cont, sprout::next(first), last, args..., *first)
? sprout::algorithm::detail::join_impl_1<Result>(
first_cont, last_cont,
sprout::next(first), last,
args..., *first
)
: sprout::algorithm::detail::join_impl<Result>(sprout::next(first_cont), last_cont, args...)
;
}
template<typename Result, typename ContainerInputIterator, typename... Args>
template<typename Result, typename ContIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size == sizeof...(Args),
Result
>::type join_impl(
ContainerInputIterator first_cont,
ContainerInputIterator last_cont,
ContIterator first_cont,
ContIterator last_cont,
Args const&... args
)
{
return sprout::make<Result>(args...);
}
template<typename Result, typename ContainerInputIterator, typename... Args>
template<typename Result, typename ContIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size != sizeof...(Args),
Result
>::type join_impl(
ContainerInputIterator first_cont,
ContainerInputIterator last_cont,
ContIterator first_cont,
ContIterator last_cont,
Args const&... args
)
{
return first_cont != last_cont
? sprout::algorithm::detail::join_impl_1<Result>(first_cont, last_cont, sprout::begin(*first_cont), sprout::end(*first_cont), args...)
? sprout::algorithm::detail::join_impl_1<Result>(
first_cont, last_cont,
sprout::begin(*first_cont), sprout::end(*first_cont),
args...
)
: sprout::make<Result>(args...)
;
}
template<
typename ContainerContainer,
typename sprout::enabler_if<
sprout::is_random_access_iterator<
typename sprout::container_traits<ContainerContainer const>::iterator
>::value
&& sprout::is_random_access_iterator<
typename sprout::container_traits<
typename sprout::container_traits<ContainerContainer const>::value_type
>::iterator
>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer>::type
join(ContainerContainer const& cont_cont) {
typedef typename sprout::algorithm::result_of::join<ContainerContainer>::type result_type;
return sprout::algorithm::detail::join_impl_ra<result_type>(cont_cont);
}
template<
typename ContainerContainer,
typename sprout::enabler_if<!(
sprout::is_random_access_iterator<
typename sprout::container_traits<ContainerContainer const>::iterator
>::value
&& sprout::is_random_access_iterator<
typename sprout::container_traits<
typename sprout::container_traits<ContainerContainer const>::value_type
>::iterator
>::value
)>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer>::type
join(ContainerContainer const& cont_cont) {
typedef typename sprout::algorithm::result_of::join<ContainerContainer>::type result_type;
return sprout::algorithm::detail::join_impl<result_type>(
sprout::begin(cont_cont),
sprout::end(cont_cont)
);
}
} // namespace detail
//
// join
//
template<typename ContainerContainer>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer>::type join(
ContainerContainer const& cont_cont
)
{
return sprout::algorithm::detail::join_impl<typename sprout::algorithm::result_of::join<ContainerContainer>::type>(
sprout::begin(cont_cont),
sprout::end(cont_cont)
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer>::type
join(ContainerContainer const& cont_cont) {
return sprout::algorithm::detail::join(cont_cont);
}
namespace detail {
template<typename Result, typename ContIterator, typename SepIterator, typename SizeIterator, typename Sizes>
inline SPROUT_CONSTEXPR typename sprout::container_traits<Result>::value_type
join_impl_ra_2(
ContIterator first_cont,
SepIterator first,
SizeIterator found,
Sizes const& sizes,
sprout::index_t idx
)
{
typedef typename sprout::container_traits<Result>::value_type value_type;
return found == sizes.end() ? value_type()
: (found - sizes.begin()) % 2 ? first[idx - found[-1]]
: sprout::begin(first_cont[(found - sizes.begin()) / 2])[idx - (found != sizes.begin() ? found[-1] : 0)]
;
}
template<typename Result, typename ContIterator, typename SepIterator, sprout::index_t... Indexes, typename Sizes>
inline SPROUT_CONSTEXPR Result
join_impl_ra_1(
ContIterator first_cont,
SepIterator first,
sprout::index_tuple<Indexes...>,
Sizes const& sizes
)
{
return sprout::make<Result>(
sprout::algorithm::detail::join_impl_ra_2<Result>(
first_cont,
first,
sprout::range::lower_bound(sizes, Indexes + 1),
sizes,
Indexes
)...
);
}
template<typename Result, typename ContainerContainer, typename Separator>
inline SPROUT_CONSTEXPR Result
join_impl_ra(ContainerContainer const& cont_cont, Separator const& separator) {
typedef typename sprout::container_traits<Result>::difference_type size_type;
typedef sprout::array<
size_type,
sprout::container_traits<ContainerContainer>::static_size
? sprout::container_traits<ContainerContainer>::static_size * 2 - 1
: 0
> sizes_type;
return sprout::algorithm::detail::join_impl_ra_1<Result>(
sprout::begin(cont_cont),
sprout::begin(separator),
sprout::index_range<0, sprout::container_traits<Result>::static_size>::make(),
sprout::range::partial_sum(
cont_cont | sprout::adaptors::size_enumed(sprout::algorithm::detail::str_size(separator), true),
sprout::pit<sizes_type>()
)
);
}
template<typename Result, typename ContIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size == sizeof...(Args),
Result
>::type join_impl(
ContIterator first_cont,
ContIterator last_cont,
Args const&... args
);
template<typename Result, typename ContIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size != sizeof...(Args),
Result
>::type join_impl(
ContIterator first_cont,
ContIterator last_cont,
Args const&... args
);
template<typename Result, typename ContIterator, typename SepIterator, typename InputIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size == sizeof...(Args),
Result
>::type join_impl_1(
ContIterator first_cont,
ContIterator last_cont,
SepIterator sep_first,
SepIterator sep_last,
bool sep,
InputIterator first,
InputIterator last,
Args const&... args
)
{
return sprout::make<Result>(args...);
}
template<typename Result, typename ContIterator, typename SepIterator, typename InputIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size != sizeof...(Args),
Result
>::type join_impl_1(
ContIterator first_cont,
ContIterator last_cont,
SepIterator sep_first,
SepIterator sep_last,
bool sep,
InputIterator first,
InputIterator last,
Args const&... args
)
{
return first != last
? sprout::algorithm::detail::join_impl_1<Result>(
first_cont, last_cont,
sep_first, sep_last,
sep,
sprout::next(first), last,
args..., *first
)
: sep
? sprout::algorithm::detail::join_impl<Result>(
sprout::next(first_cont), last_cont,
sep_first, sep_last,
false,
args...
)
: sprout::algorithm::detail::join_impl<Result>(
first_cont, last_cont,
sep_first, sep_last,
true,
args...
)
;
}
template<typename Result, typename ContIterator, typename SepIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size == sizeof...(Args),
Result
>::type join_impl(
ContIterator first_cont,
ContIterator last_cont,
SepIterator sep_first,
SepIterator sep_last,
bool sep,
Args const&... args
)
{
return sprout::make<Result>(args...);
}
template<typename Result, typename ContIterator, typename SepIterator, typename... Args>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::container_traits<Result>::static_size != sizeof...(Args),
Result
>::type join_impl(
ContIterator first_cont,
ContIterator last_cont,
SepIterator sep_first,
SepIterator sep_last,
bool sep,
Args const&... args
)
{
return first_cont != last_cont
? sep
? sprout::algorithm::detail::join_impl_1<Result>(
first_cont, last_cont,
sep_first, sep_last,
sep,
sep_first, sep_last,
args...
)
: sprout::algorithm::detail::join_impl_1<Result>(
first_cont, last_cont,
sep_first, sep_last,
sep,
sprout::begin(*first_cont), sprout::end(*first_cont),
args...
)
: sprout::make<Result>(args...)
;
}
template<
typename ContainerContainer,
typename Separator,
typename sprout::enabler_if<
sprout::is_random_access_iterator<
typename sprout::container_traits<ContainerContainer const>::iterator
>::value
&& sprout::is_random_access_iterator<
typename sprout::container_traits<
typename sprout::container_traits<ContainerContainer const>::value_type
>::iterator
>::value
&& sprout::is_random_access_iterator<
typename sprout::container_traits<Separator const>::iterator
>::value
>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer>::type
join(ContainerContainer const& cont_cont, Separator const& separator) {
typedef typename sprout::algorithm::result_of::join<ContainerContainer>::type result_type;
return sprout::algorithm::detail::join_impl_ra<result_type>(cont_cont, separator);
}
template<
typename ContainerContainer,
typename Separator,
typename sprout::enabler_if<!(
sprout::is_random_access_iterator<
typename sprout::container_traits<ContainerContainer const>::iterator
>::value
&& sprout::is_random_access_iterator<
typename sprout::container_traits<
typename sprout::container_traits<ContainerContainer const>::value_type
>::iterator
>::value
&& sprout::is_random_access_iterator<
typename sprout::container_traits<Separator const>::iterator
>::value
)>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer>::type
join(ContainerContainer const& cont_cont, Separator const& separator) {
typedef typename sprout::algorithm::result_of::join<ContainerContainer>::type result_type;
return sprout::algorithm::detail::join_impl<result_type>(
sprout::begin(cont_cont),
sprout::end(cont_cont),
sprout::begin(separator),
sprout::end(separator),
false
);
}
} // namespace detail
//
// join
//
template<typename ContainerContainer, typename Separator>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join<ContainerContainer, Separator>::type
join(ContainerContainer const& cont_cont, Separator const& separator) {
return sprout::algorithm::detail::join(cont_cont, separator);
}
} // namespace algorithm
} // namespace sprout

View file

@ -1,108 +0,0 @@
#ifndef SPROUT_ALGORITHM_STRING_JOIN2_HPP
#define SPROUT_ALGORITHM_STRING_JOIN2_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/operation/fixed/append_back.hpp>
namespace sprout {
namespace algorithm {
namespace result_of {
//
// join2
//
template<typename ContainerContainer, typename Separator>
struct join2 {
public:
typedef typename sprout::container_transform_traits<
typename sprout::container_traits<ContainerContainer>::value_type
>::template rebind_size<
sprout::container_traits<ContainerContainer>::static_size != 0
? (
sprout::container_traits<
typename sprout::container_traits<ContainerContainer>::value_type
>::static_size
+ (sprout::container_traits<ContainerContainer>::static_size - 1) * (
sprout::container_traits<Separator>::static_size
+ sprout::container_traits<
typename sprout::container_traits<ContainerContainer>::value_type
>::static_size
)
)
: 0
>::type type;
};
} // namespace result_of
namespace detail {
template<typename Result, typename ContainerIterator, typename Separator, typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
(sprout::container_traits<Container>::static_size == sprout::container_traits<Result>::static_size),
Result
>::type join2_impl_1(
ContainerIterator first,
ContainerIterator last,
Separator const& separator,
Container const& current
)
{
return current;
}
template<typename Result, typename ContainerIterator, typename Separator, typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
(sprout::container_traits<Container>::static_size < sprout::container_traits<Result>::static_size),
Result
>::type join2_impl_1(
ContainerIterator first,
ContainerIterator last,
Separator const& separator,
Container const& current
)
{
return sprout::algorithm::detail::join2_impl_1<Result>(
sprout::next(first),
last,
separator,
sprout::fixed::append_back(sprout::fixed::append_back(current, separator), *first)
);
}
template<typename Result, typename ContainerIterator, typename Separator>
inline SPROUT_CONSTEXPR Result join2_impl(
ContainerIterator first,
ContainerIterator last,
Separator const& separator
)
{
return first != last
? sprout::algorithm::detail::join2_impl_1<Result>(
sprout::next(first),
last,
separator,
*first
)
: sprout::make<Result>()
;
}
} // namespace detail
//
// join2
//
template<typename ContainerContainer, typename Separator>
inline SPROUT_CONSTEXPR typename sprout::algorithm::result_of::join2<ContainerContainer, Separator>::type join2(
ContainerContainer const& cont_cont,
Separator const& separator
)
{
return sprout::algorithm::detail::join2_impl<typename sprout::algorithm::result_of::join2<ContainerContainer, Separator>::type>(
sprout::begin(cont_cont),
sprout::end(cont_cont),
separator
);
}
} // namespace algorithm
} // namespace sprout
#endif // #ifndef SPROUT_ALGORITHM_STRING_JOIN2_HPP