[libcxx-commits] [libcxx] 1323461 - [libc++] Add utilites for instantiating functions with multiple types
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Nov 21 11:35:12 PST 2022
Author: Nikolas Klauser
Date: 2022-11-21T20:35:06+01:00
New Revision: 1323461fe7cf92f6b7bdb1f088fe4c748660a046
URL: https://github.com/llvm/llvm-project/commit/1323461fe7cf92f6b7bdb1f088fe4c748660a046
DIFF: https://github.com/llvm/llvm-project/commit/1323461fe7cf92f6b7bdb1f088fe4c748660a046.diff
LOG: [libc++] Add utilites for instantiating functions with multiple types
We currently call a lot of functions with the same list of types. To avoid forgetting any of them, this patch adds type_lists and utilities for it. Specifically, it adds
- `type_list` - This is just a list of types
- `concatenate` - This allows concatenating type_lists
- `for_each` - Iterate over a type_list
Reviewed By: ldionne, #libc
Spies: jloser, EricWF, libcxx-commits
Differential Revision: https://reviews.llvm.org/D137476
Added:
libcxx/test/support/test.support/type_algorithms.pass.cpp
libcxx/test/support/type_algorithms.h
Modified:
libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp
libcxx/test/std/language.support/support.limits/limits/is_specialized.pass.cpp
libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
libcxx/test/support/test_iterators.h
Removed:
################################################################################
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp
index 5ca0ce9339928..c2410568b3e3b 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp
@@ -24,6 +24,7 @@
#include "almost_satisfies_types.h"
#include "test_iterators.h"
+#include "type_algorithms.h"
template <class In, class Out = In, class Sent = sentinel_wrapper<In>>
concept HasCopyIt = requires(In in, Sent sent, Out out) { std::ranges::copy(in, sent, out); };
@@ -94,48 +95,28 @@ constexpr void test_iterators() {
}
}
-template <class In, class Out>
-constexpr void test_sentinels() {
- test_iterators<In, Out>();
- test_iterators<In, Out, sized_sentinel<In>>();
- test_iterators<In, Out, sentinel_wrapper<In>>();
-}
-
-template <class Out>
-constexpr void test_in_iterators() {
- test_iterators<cpp20_input_iterator<int*>, Out, sentinel_wrapper<cpp20_input_iterator<int*>>>();
- test_sentinels<forward_iterator<int*>, Out>();
- test_sentinels<bidirectional_iterator<int*>, Out>();
- test_sentinels<random_access_iterator<int*>, Out>();
- test_sentinels<contiguous_iterator<int*>, Out>();
-}
-
-template <class Out>
-constexpr void test_proxy_in_iterators() {
- test_iterators<ProxyIterator<cpp20_input_iterator<int*>>, Out, sentinel_wrapper<ProxyIterator<cpp20_input_iterator<int*>>>>();
- test_iterators<ProxyIterator<forward_iterator<int*>>, Out>();
- test_iterators<ProxyIterator<bidirectional_iterator<int*>>, Out>();
- test_iterators<ProxyIterator<random_access_iterator<int*>>, Out>();
- test_iterators<ProxyIterator<contiguous_iterator<int*>>, Out>();
-}
-
constexpr bool test() {
- test_in_iterators<cpp20_input_iterator<int*>>();
- test_in_iterators<forward_iterator<int*>>();
- test_in_iterators<bidirectional_iterator<int*>>();
- test_in_iterators<random_access_iterator<int*>>();
- test_in_iterators<contiguous_iterator<int*>>();
-
- test_proxy_in_iterators<ProxyIterator<cpp20_input_iterator<int*>>>();
- test_proxy_in_iterators<ProxyIterator<forward_iterator<int*>>>();
- test_proxy_in_iterators<ProxyIterator<bidirectional_iterator<int*>>>();
- test_proxy_in_iterators<ProxyIterator<random_access_iterator<int*>>>();
- test_proxy_in_iterators<ProxyIterator<contiguous_iterator<int*>>>();
+ meta::for_each(meta::forward_iterator_list<int*>{}, []<class Out>() {
+ test_iterators<cpp20_input_iterator<int*>, Out, sentinel_wrapper<cpp20_input_iterator<int*>>>();
+ test_iterators<ProxyIterator<cpp20_input_iterator<int*>>,
+ ProxyIterator<Out>,
+ sentinel_wrapper<ProxyIterator<cpp20_input_iterator<int*>>>>();
+
+ meta::for_each(meta::forward_iterator_list<int*>{}, []<class In>() {
+ test_iterators<In, Out>();
+ test_iterators<In, Out, sized_sentinel<In>>();
+ test_iterators<In, Out, sentinel_wrapper<In>>();
+
+ test_iterators<ProxyIterator<In>, ProxyIterator<Out>>();
+ test_iterators<ProxyIterator<In>, ProxyIterator<Out>, sized_sentinel<ProxyIterator<In>>>();
+ test_iterators<ProxyIterator<In>, ProxyIterator<Out>, sentinel_wrapper<ProxyIterator<In>>>();
+ });
+ });
{ // check that ranges::dangling is returned
std::array<int, 4> out;
std::same_as<std::ranges::in_out_result<std::ranges::dangling, int*>> auto ret =
- std::ranges::copy(std::array {1, 2, 3, 4}, out.data());
+ std::ranges::copy(std::array{1, 2, 3, 4}, out.data());
assert(ret.out == out.data() + 4);
assert((out == std::array{1, 2, 3, 4}));
}
diff --git a/libcxx/test/std/language.support/support.limits/limits/is_specialized.pass.cpp b/libcxx/test/std/language.support/support.limits/limits/is_specialized.pass.cpp
index 3f3ecbd336dcd..0c39f9fccce57 100644
--- a/libcxx/test/std/language.support/support.limits/limits/is_specialized.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/limits/is_specialized.pass.cpp
@@ -26,11 +26,11 @@
#include <limits>
#include <complex>
-#include "test_macros.h"
+#include "type_algorithms.h"
-template <class T>
-void test()
-{
+struct Test {
+ template <class T>
+ void operator()() {
static_assert(std::numeric_limits<T>::is_specialized,
"std::numeric_limits<T>::is_specialized");
static_assert(std::numeric_limits<const T>::is_specialized,
@@ -39,37 +39,15 @@ void test()
"std::numeric_limits<volatile T>::is_specialized");
static_assert(std::numeric_limits<const volatile T>::is_specialized,
"std::numeric_limits<const volatile T>::is_specialized");
-}
+ }
+};
int main(int, char**)
{
- test<bool>();
- test<char>();
- test<wchar_t>();
-#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
- test<char8_t>();
-#endif
- test<char16_t>();
- test<char32_t>();
- test<signed char>();
- test<unsigned char>();
- test<signed short>();
- test<unsigned short>();
- test<signed int>();
- test<unsigned int>();
- test<signed long>();
- test<unsigned long>();
- test<signed long long>();
- test<unsigned long long>();
-#ifndef TEST_HAS_NO_INT128
- test<__int128_t>();
- test<__uint128_t>();
-#endif
- test<float>();
- test<double>();
- test<long double>();
- static_assert(!std::numeric_limits<std::complex<double> >::is_specialized,
- "!std::numeric_limits<std::complex<double> >::is_specialized");
+ meta::for_each(meta::arithmetic_types(), Test());
+
+ static_assert(!std::numeric_limits<std::complex<double> >::is_specialized,
+ "!std::numeric_limits<std::complex<double> >::is_specialized");
return 0;
}
diff --git a/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
index 3b991c54e6c91..3e17d07e2d811 100644
--- a/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
@@ -17,7 +17,9 @@
#include "min_allocator.h"
+#include "make_string.h"
#include "test_macros.h"
+#include "type_algorithms.h"
template <class S>
TEST_CONSTEXPR_CXX20 void
@@ -57,17 +59,24 @@ test(S s, typename S::size_type pos)
template <class S>
TEST_CONSTEXPR_CXX20 void test_string() {
test(S(), 0);
- test(S("123"), 0);
- test(S("123"), 1);
- test(S("123"), 2);
- test(S("123"), 3);
+ test(S(MAKE_CSTRING(typename S::value_type, "123")), 0);
+ test(S(MAKE_CSTRING(typename S::value_type, "123")), 1);
+ test(S(MAKE_CSTRING(typename S::value_type, "123")), 2);
+ test(S(MAKE_CSTRING(typename S::value_type, "123")), 3);
}
-TEST_CONSTEXPR_CXX20 bool test() {
- test_string<std::string>();
+struct TestCaller {
+ template <class T>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ test_string<std::basic_string<T> >();
#if TEST_STD_VER >= 11
- test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+ test_string<std::basic_string<T, std::char_traits<T>, min_allocator<T> > >();
#endif
+ }
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ meta::for_each(meta::character_types(), TestCaller());
return true;
}
diff --git a/libcxx/test/support/test.support/type_algorithms.pass.cpp b/libcxx/test/support/test.support/type_algorithms.pass.cpp
new file mode 100644
index 0000000000000..f94487d1c868e
--- /dev/null
+++ b/libcxx/test/support/test.support/type_algorithms.pass.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <algorithm>
+#include <cassert>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+// concatenate
+static_assert(std::is_same<meta::concatenate_t<meta::type_list<> >, meta::type_list<> >::value, "");
+static_assert(std::is_same<meta::concatenate_t<meta::type_list<int> >, meta::type_list<int> >::value, "");
+static_assert(
+ std::is_same<meta::concatenate_t<meta::type_list<int>, meta::type_list<long> >, meta::type_list<int, long> >::value,
+ "");
+static_assert(
+ std::is_same<meta::concatenate_t<meta::type_list<int>, meta::type_list<long>, meta::type_list<long long> >,
+ meta::type_list<int, long, long long> >::value,
+ "");
+
+// apply_all
+template <int N>
+class NumT {};
+
+struct ApplyAllTest {
+ bool* is_called_array_;
+
+ TEST_CONSTEXPR ApplyAllTest(bool* is_called_array) : is_called_array_(is_called_array) {}
+
+ template <int N>
+ TEST_CONSTEXPR_CXX20 void check_num(NumT<N>) {
+ assert(!is_called_array_[N]);
+ is_called_array_[N] = true;
+ }
+
+ template <int N, int M>
+ TEST_CONSTEXPR_CXX20 void check_num(NumT<N>, NumT<M>) {
+ assert(!is_called_array_[N + M]);
+ is_called_array_[N + M] = true;
+ }
+
+ template <class... Types>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ check_num(Types()...);
+ }
+};
+
+struct Identity {
+ TEST_CONSTEXPR bool operator()(bool b) const { return b; }
+};
+
+TEST_CONSTEXPR_CXX20 void test_for_each() {
+ bool is_called_array[3] = {};
+ meta::for_each(meta::type_list<NumT<0>, NumT<1>, NumT<2> >(), ApplyAllTest(is_called_array));
+ assert(std::all_of(is_called_array, is_called_array + 3, Identity()));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ test_for_each();
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 20
+ static_assert(test());
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index d5381b5de1dfc..369393d3d5d4e 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -18,6 +18,7 @@
#include <utility>
#include "test_macros.h"
+#include "type_algorithms.h"
// This iterator meets C++20's Cpp17OutputIterator requirements, as described
@@ -1297,6 +1298,23 @@ template <std::ranges::input_range R>
requires std::ranges::viewable_range<R&&>
ProxyRange(R&&) -> ProxyRange<std::views::all_t<R&&>>;
+namespace meta {
+template <class Ptr>
+using random_access_iterator_list = type_list<Ptr, contiguous_iterator<Ptr>, random_access_iterator<Ptr>>;
+
+template <class Ptr>
+using bidirectional_iterator_list =
+ concatenate_t<random_access_iterator_list<Ptr>, type_list<bidirectional_iterator<Ptr>>>;
+
+template <class Ptr>
+using forward_iterator_list = concatenate_t<bidirectional_iterator_list<Ptr>, type_list<forward_iterator<Ptr>>>;
+
+template <class Ptr>
+using cpp20_input_iterator_list =
+ concatenate_t<forward_iterator_list<Ptr>, type_list<cpp20_input_iterator<Ptr>, cpp17_input_iterator<Ptr>>>;
+
+} // namespace meta
+
#endif // TEST_STD_VER > 17
#endif // SUPPORT_TEST_ITERATORS_H
diff --git a/libcxx/test/support/type_algorithms.h b/libcxx/test/support/type_algorithms.h
new file mode 100644
index 0000000000000..823978b54376c
--- /dev/null
+++ b/libcxx/test/support/type_algorithms.h
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_SUPPORT_TYPE_ALGORITHMS_H
+#define TEST_SUPPORT_TYPE_ALGORITHMS_H
+
+#include <type_traits>
+
+#include "test_macros.h"
+
+namespace meta {
+template <class... Types>
+struct type_list {};
+
+// concatenates N type_lists to one (for N >= 1)
+template <class...>
+struct concatenate;
+
+template <class... Types>
+using concatenate_t = typename concatenate<Types...>::type;
+
+// for_each takes a type_list calls f with each element as the first template argument
+template <class... Types, class Functor>
+TEST_CONSTEXPR_CXX14 void for_each(type_list<Types...>, Functor f);
+
+// impl
+template <class... Types>
+struct concatenate<type_list<Types...> > {
+ using type = type_list<Types...>;
+};
+
+template <class... Types1, class... Types2>
+struct concatenate<type_list<Types1...>, type_list<Types2...> > {
+ using type = type_list<Types1..., Types2...>;
+};
+
+template <class... Types1, class... Types2, class... Rest>
+struct concatenate<type_list<Types1...>, type_list<Types2...>, Rest...> {
+ using type = concatenate_t<type_list<Types1..., Types2...>, Rest...>;
+};
+
+template <class... Types>
+TEST_CONSTEXPR_CXX14 void swallow(Types...) {}
+
+template <class... Types, class Functor>
+TEST_CONSTEXPR_CXX14 void for_each(type_list<Types...>, Functor f) {
+ swallow((f.template operator()<Types>(), 0)...);
+}
+
+// type categories defined in [basic.fundamental] plus extensions (without CV-qualifiers)
+
+using character_types =
+ type_list<char
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ ,
+ wchar_t
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
+ ,
+ char8_t
+#endif
+#if TEST_STD_VER >= 11
+ ,
+ char16_t,
+ char32_t
+#endif
+ >;
+
+using signed_integer_types =
+ type_list<signed char,
+ short,
+ int,
+ long,
+ long long
+#ifndef TEST_HAS_NO_INT128
+ ,
+ __int128_t
+#endif
+ >;
+
+using unsigned_integer_types =
+ type_list<unsigned char,
+ unsigned short,
+ unsigned int,
+ unsigned long,
+ unsigned long long
+#ifndef TEST_HAS_NO_INT128
+ ,
+ __uint128_t
+#endif
+ >;
+
+using integral_types = concatenate_t<character_types, signed_integer_types, unsigned_integer_types, type_list<bool> >;
+
+using floating_point_types = type_list<float, double, long double>;
+
+using arithmetic_types = concatenate_t<integral_types, floating_point_types>;
+} // namespace meta
+
+#endif // TEST_SUPPORT_TYPE_ALGORITHMS_H
More information about the libcxx-commits
mailing list