1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-05-15 17:46:39 +08:00
CMake/Utilities/std/cmext/algorithm
Kitware Robot bdca8b01d2 Modernize: Use #pragma once in all header files
#pragma once is a widely supported compiler pragma, even though it is
not part of the C++ standard. Many of the issues keeping #pragma once
from being standardized (distributed filesystems, build farms, hard
links, etc.) do not apply to CMake - it is easy to build CMake on a
single machine. CMake also does not install any header files which can
be consumed by other projects (though cmCPluginAPI.h has been
deliberately omitted from this conversion in case anyone is still using
it.) Finally, #pragma once has been required to build CMake since at
least August 2017 (7f29bbe6 enabled server mode unconditionally, which
had been using #pragma once since September 2016 (b13d3e0d)). The fact
that we now require C++11 filters out old compilers, and it is unlikely
that there is a compiler which supports C++11 but does not support
#pragma once.
2020-09-03 09:30:21 -04:00

249 lines
9.0 KiB
C++

// -*-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. */
#pragma once
#include <algorithm>
#include <iterator>
#include <memory>
#include <utility>
#include <cm/type_traits>
#include <cmext/iterator>
#include <cmext/type_traits>
#if defined(__SUNPRO_CC) && defined(__sparc)
# include <list>
# include <vector>
#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
#if defined(__SUNPRO_CC)
template <typename Iterator, typename Key>
auto contains(Iterator first, Iterator last, Key const& key,
detail::overload_selector<1>) -> decltype(first->first == key)
#else
template <typename Iterator, typename Key,
cm::enable_if_t<
cm::is_input_iterator<Iterator>::value &&
std::is_convertible<Key,
typename std::iterator_traits<
Iterator>::value_type::first_type>::value,
int> = 0>
bool contains(Iterator first, Iterator last, Key const& key)
#endif
{
return std::find_if(
first, last,
[&key](
typename std::iterator_traits<Iterator>::value_type const& item) {
return item.first == key;
}) != last;
}
#if defined(__SUNPRO_CC)
template <typename Iterator, typename Key>
bool contains(Iterator first, Iterator last, Key const& key,
detail::overload_selector<0>)
#else
template <
typename Iterator, typename Key,
cm::enable_if_t<
cm::is_input_iterator<Iterator>::value &&
std::is_convertible<
Key, typename std::iterator_traits<Iterator>::value_type>::value,
int> = 0>
bool contains(Iterator first, Iterator last, Key const& key)
#endif
{
return std::find(first, last, key) != last;
}
#if defined(__SUNPRO_CC)
template <typename Iterator, typename Key>
bool contains(Iterator first, Iterator last, Key const& key)
{
return contains(first, last, key, detail::overload_selector<1>{});
}
#endif
#if defined(__SUNPRO_CC)
template <typename Range, typename Key>
auto contains(Range const& range, Key const& key, detail::overload_selector<1>)
-> decltype(range.find(key) != range.end())
#else
template <
typename Range, typename Key,
cm::enable_if_t<cm::is_associative_container<Range>::value ||
cm::is_unordered_associative_container<Range>::value,
int> = 0>
bool contains(Range const& range, Key const& key)
#endif
{
return range.find(key) != range.end();
}
#if defined(__SUNPRO_CC)
template <typename Range, typename Key>
bool contains(Range const& range, Key const& key, detail::overload_selector<0>)
#else
template <
typename Range, typename Key,
cm::enable_if_t<cm::is_input_range<Range>::value &&
!(cm::is_associative_container<Range>::value ||
cm::is_unordered_associative_container<Range>::value),
int> = 0>
bool contains(Range const& range, Key const& key)
#endif
{
return std::find(std::begin(range), std::end(range), key) != std::end(range);
}
#if defined(__SUNPRO_CC)
template <typename Range, typename Key>
bool contains(Range const& range, Key const& key)
{
return contains(range, key, detail::overload_selector<1>{});
}
#endif
} // namespace cm