mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-05 21:31:08 -06:00
Stl support: cm::append now supports any sequential container
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user