123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- // -*-c++-*-
- // vim: set ft=cpp:
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #ifndef cmext_algorithm
- #define cmext_algorithm
- #include <algorithm>
- #include <iterator>
- #include <memory>
- #include <utility>
- #include <cm/type_traits>
- #include <cmext/iterator>
- #if defined(__SUNPRO_CC) && defined(__sparc)
- # include <list>
- # include <vector>
- #else
- # include <cmext/type_traits>
- #endif
- namespace cm {
- #if defined(__SUNPRO_CC) && defined(__sparc)
- // Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile
- // templates with constraints.
- // So, on this platform, use only simple templates.
- # define APPEND_TWO(C1, C2) \
- template <typename T, typename U> \
- void append(C1<std::unique_ptr<T>>& v, C2<std::unique_ptr<U>>&& r) \
- { \
- std::transform( \
- r.begin(), r.end(), std::back_inserter(v), \
- [](std::unique_ptr<U>& item) { return std::move(item); }); \
- r.clear(); \
- } \
- \
- template <typename T, typename U> \
- void append(C1<T*>& v, C2<std::unique_ptr<U>> const& r) \
- { \
- std::transform( \
- r.begin(), r.end(), std::back_inserter(v), \
- [](const std::unique_ptr<U>& item) { return item.get(); }); \
- }
- # define APPEND_ONE(C) \
- template <typename T, typename InputIt, \
- cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = \
- 0> \
- void append(C<T>& v, InputIt first, InputIt last) \
- { \
- v.insert(v.end(), first, last); \
- } \
- \
- template <typename T, typename Range, \
- cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0> \
- void append(C<T>& v, Range const& r) \
- { \
- v.insert(v.end(), r.begin(), r.end()); \
- }
- # define APPEND(C) \
- APPEND_TWO(C, C) \
- APPEND_ONE(C)
- # define APPEND_MIX(C1, C2) \
- APPEND_TWO(C1, C2) \
- APPEND_TWO(C2, C1)
- // For now, manage only support for std::vector and std::list.
- // Other sequential container support can be added if needed.
- APPEND(std::vector)
- APPEND(std::list)
- APPEND_MIX(std::vector, std::list)
- # undef APPEND
- # undef APPEND_MIX
- # undef APPEND_TWO
- # undef APPEND_ONE
- #else
- template <
- typename Container1, typename Container2,
- cm::enable_if_t<
- cm::is_sequence_container<Container1>::value &&
- cm::is_unique_ptr<typename Container1::value_type>::value &&
- cm::is_unique_ptr<typename Container2::value_type>::value &&
- std::is_convertible<typename Container2::value_type::pointer,
- typename Container1::value_type::pointer>::value,
- int> = 0>
- void append(Container1& v, Container2&& r)
- {
- std::transform(
- r.begin(), r.end(), std::back_inserter(v),
- [](typename Container2::value_type& item) { return std::move(item); });
- r.clear();
- }
- template <typename Container1, typename Container2,
- cm::enable_if_t<
- cm::is_sequence_container<Container1>::value &&
- std::is_pointer<typename Container1::value_type>::value &&
- cm::is_unique_ptr<typename Container2::value_type>::value &&
- std::is_convertible<typename Container2::value_type::pointer,
- typename Container1::value_type>::value,
- int> = 0>
- # if defined(__SUNPRO_CC)
- void append(Container1& v, Container2 const& r, detail::overload_selector<0>)
- # else
- void append(Container1& v, Container2 const& r)
- # endif
- {
- std::transform(
- r.begin(), r.end(), std::back_inserter(v),
- [](const typename Container2::value_type& item) { return item.get(); });
- }
- template <
- typename Container, typename InputIt,
- cm::enable_if_t<
- cm::is_sequence_container<Container>::value &&
- cm::is_input_iterator<InputIt>::value &&
- std::is_convertible<typename std::iterator_traits<InputIt>::value_type,
- typename Container::value_type>::value,
- int> = 0>
- void append(Container& v, InputIt first, InputIt last)
- {
- v.insert(v.end(), first, last);
- }
- template <typename Container, typename Range,
- cm::enable_if_t<
- cm::is_sequence_container<Container>::value &&
- cm::is_input_range<Range>::value &&
- !cm::is_unique_ptr<typename Container::value_type>::value &&
- !cm::is_unique_ptr<typename Range::value_type>::value &&
- std::is_convertible<typename Range::value_type,
- typename Container::value_type>::value,
- int> = 0>
- # if defined(__SUNPRO_CC)
- void append(Container& v, Range const& r, detail::overload_selector<1>)
- # else
- void append(Container& v, Range const& r)
- # endif
- {
- v.insert(v.end(), r.begin(), r.end());
- }
- # if defined(__SUNPRO_CC)
- template <typename T, typename U>
- void append(T& v, U const& r)
- {
- cm::append(v, r, detail::overload_selector<1>{});
- }
- # endif
- #endif
- } // namespace cm
- #endif
|