|
@@ -10,43 +10,154 @@
|
|
|
#include <iterator>
|
|
|
#include <memory>
|
|
|
#include <utility>
|
|
|
-#include <vector>
|
|
|
|
|
|
#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 {
|
|
|
|
|
|
-template <typename T>
|
|
|
-void append(std::vector<std::unique_ptr<T>>& v,
|
|
|
- std::vector<std::unique_ptr<T>>&& r)
|
|
|
+#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),
|
|
|
- [](std::unique_ptr<T>& item) { return std::move(item); });
|
|
|
+ std::transform(
|
|
|
+ r.begin(), r.end(), std::back_inserter(v),
|
|
|
+ [](typename Container2::value_type& item) { return std::move(item); });
|
|
|
r.clear();
|
|
|
}
|
|
|
|
|
|
-template <typename T>
|
|
|
-void append(std::vector<T*>& v, std::vector<std::unique_ptr<T>> const& r)
|
|
|
+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 std::unique_ptr<T>& item) { return item.get(); });
|
|
|
+ std::transform(
|
|
|
+ r.begin(), r.end(), std::back_inserter(v),
|
|
|
+ [](const typename Container2::value_type& item) { return item.get(); });
|
|
|
}
|
|
|
|
|
|
-template <typename T, typename InputIt,
|
|
|
- cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = 0>
|
|
|
-void append(std::vector<T>& v, InputIt first, InputIt last)
|
|
|
+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 T, typename Range,
|
|
|
- cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0>
|
|
|
-void append(std::vector<T>& v, Range const& r)
|
|
|
+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
|