Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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
- Loading branch information
1 parent
bd68070
commit 1323461
Showing
6 changed files
with
243 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |