mirror of
https://github.com/Kitware/CMake.git
synced 2025-05-15 17:46:39 +08:00

#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.
249 lines
9.0 KiB
C++
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
|