summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Tests/CMakeLib/testCMExtAlgorithm.cxx1
-rw-r--r--Utilities/std/cmext/algorithm143
-rw-r--r--Utilities/std/cmext/type_traits18
3 files changed, 146 insertions, 16 deletions
diff --git a/Tests/CMakeLib/testCMExtAlgorithm.cxx b/Tests/CMakeLib/testCMExtAlgorithm.cxx
index c731b72..b8319c3 100644
--- a/Tests/CMakeLib/testCMExtAlgorithm.cxx
+++ b/Tests/CMakeLib/testCMExtAlgorithm.cxx
@@ -1,5 +1,6 @@
#include <iostream>
#include <memory>
+#include <type_traits>
#include <utility>
#include <vector>
diff --git a/Utilities/std/cmext/algorithm b/Utilities/std/cmext/algorithm
index 609860c..44e61f4 100644
--- a/Utilities/std/cmext/algorithm
+++ b/Utilities/std/cmext/algorithm
@@ -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
diff --git a/Utilities/std/cmext/type_traits b/Utilities/std/cmext/type_traits
index da6550d..00984cb 100644
--- a/Utilities/std/cmext/type_traits
+++ b/Utilities/std/cmext/type_traits
@@ -10,6 +10,24 @@
namespace cm {
+#if defined(__SUNPRO_CC)
+// Oracle DeveloperStudio C++ compiler do not support overloaded templates with
+// same signature but different constraints over template arguments
+// (i.e. meta-programming).
+// As a work-around, use a structure to avoid templates with same signature.
+namespace detail {
+template <int N>
+struct overload_selector : overload_selector<N - 1>
+{
+};
+
+template <>
+struct overload_selector<0>
+{
+};
+}
+#endif
+
// type traits for managed pointer types
template <typename>
struct is_unique_ptr : std::false_type