Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P2165R4: Compatibility Between tuple, pair, And tuple-like Objects #3372

Merged
merged 45 commits into from
Feb 26, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
61eff70
Add feature test macro
JMazurkiewicz Dec 15, 2022
dee5c28
Apply changes from `range.subrange`
JMazurkiewicz Dec 16, 2022
079cc4f
Apply changes from `range.elements.view`
JMazurkiewicz Dec 16, 2022
4394897
Apply changes from `associative.general`
JMazurkiewicz Dec 16, 2022
2f17692
Implement `basic_common_reference` and `common_type` for `tuple-like`…
JMazurkiewicz Dec 16, 2022
14b2efc
Implement `common_reference` and `common_type` tests
JMazurkiewicz Jan 23, 2023
8ab8d84
Remove useless forward declarations of `get(tuple)` function
JMazurkiewicz Jan 23, 2023
f812a39
Test changes to `[associative.general]`
JMazurkiewicz Jan 23, 2023
e19cfea
New `tuple` members + tests
JMazurkiewicz Jan 29, 2023
cabb123
Implement comparison operators + tests
JMazurkiewicz Jan 29, 2023
c397fda
Make `common_reference` tests strict
JMazurkiewicz Jan 29, 2023
78146ba
Test update
JMazurkiewicz Jan 29, 2023
d8e699f
Implement tuple special functions + tests
JMazurkiewicz Jan 29, 2023
cc13eed
Polishing up 💎
JMazurkiewicz Jan 29, 2023
eb44051
ADD WORKAROUND FOR LLVM-59827
JMazurkiewicz Jan 30, 2023
60e8b16
Improve new assignment operators
JMazurkiewicz Jan 30, 2023
848a00a
Skip some LLVM tests
JMazurkiewicz Jan 30, 2023
2c4d425
`common_type<pair>` and `common_reference<pair>` should be available …
JMazurkiewicz Jan 30, 2023
91322ab
Fix constructors (again), no fix for comparisons (yet)
JMazurkiewicz Jan 30, 2023
f5bac0e
Quick comment fix
JMazurkiewicz Jan 30, 2023
14cad2d
YEAH, I THINK COMPARISON OPERATORS ARE FINE NOW
JMazurkiewicz Jan 30, 2023
6a860d5
Remove redundant remove_cvref_t
JMazurkiewicz Jan 30, 2023
a168536
Comment DevCom-10265322 workaround
JMazurkiewicz Jan 31, 2023
75a0964
Implement SFINAE-friendly <=> (thanks @frederick-vs-ja!)
JMazurkiewicz Jan 31, 2023
325884d
Turn traits structures back into variables
JMazurkiewicz Jan 31, 2023
1bc4ff3
Add extra tests for DevCom-10265237
JMazurkiewicz Jan 31, 2023
7b92933
Try to fix `/permissive` tests
JMazurkiewicz Jan 31, 2023
203be06
Replace fold expressions with `conjunction_v`
JMazurkiewicz Jan 31, 2023
69accc6
Fix ICEs with this one simple trick!
JMazurkiewicz Feb 1, 2023
cf148b9
Address some comments from @StephanTLavavej
JMazurkiewicz Feb 3, 2023
bb1b1ab
More comments!
JMazurkiewicz Feb 3, 2023
ae8b0ce
Quick `static_assert` fix
JMazurkiewicz Feb 3, 2023
c5e3ce8
Merge branch 'main' into tuple_like
JMazurkiewicz Feb 3, 2023
760b0c8
More `signed, unsigned` => `int, unsigned int`.
StephanTLavavej Feb 3, 2023
c0a3e01
Merge branch 'main' into tuple_like
JMazurkiewicz Feb 14, 2023
1e5b263
Move libcxx skips
JMazurkiewicz Feb 14, 2023
baf59fe
Merge branch 'main' into tuple_like
CaseyCarter Feb 21, 2023
a237351
Remove `int main() {} // COMPILE-ONLY` from tests
JMazurkiewicz Feb 21, 2023
64c2276
`static_cast<void>` -> `(void)`
JMazurkiewicz Feb 22, 2023
fd16c01
Trailing return type for `operator<=>`
JMazurkiewicz Feb 22, 2023
b12c9de
Three way comparison got "DeMorganed"
JMazurkiewicz Feb 22, 2023
880b079
Let's do partial specialization on `_Const_assignment` (for @strega-n…
JMazurkiewicz Feb 23, 2023
49b9c17
Merge branch 'main' into tuple_like
JMazurkiewicz Feb 23, 2023
bbae2c8
Add parens to restore clang-format.
StephanTLavavej Feb 23, 2023
01bb99c
Fix issues found during mirroring.
StephanTLavavej Feb 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -5467,13 +5467,17 @@ namespace ranges {
#endif // _HAS_CXX23

template <class _Tuple, size_t _Index>
concept _Has_tuple_element = //
concept _Has_tuple_element =
#if _HAS_CXX23
_Tuple_like<_Tuple> && _Index < tuple_size_v<_Tuple>;
#else // ^^^ C++23 / C++20 vvv
requires(_Tuple __t) {
typename tuple_size<_Tuple>::type;
requires _Index < tuple_size_v<_Tuple>;
typename tuple_element_t<_Index, _Tuple>;
{ _STD get<_Index>(__t) } -> convertible_to<const tuple_element_t<_Index, _Tuple>&>;
};
#endif // C++20

template <class _Tuple, size_t _Index>
concept _Returnable_element = is_reference_v<_Tuple> || move_constructible<tuple_element_t<_Index, _Tuple>>;
Expand Down
229 changes: 217 additions & 12 deletions stl/inc/tuple

Large diffs are not rendered by default.

44 changes: 27 additions & 17 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -1099,14 +1099,30 @@ struct _Is_allocator<_Ty, void_t<typename _Ty::value_type, decltype(_STD declval

// deduction guide utilities (N4892 [associative.general]/2)
template <class _Iter>
using _Guide_key_t = remove_const_t<typename iterator_traits<_Iter>::value_type::first_type>;
using _Guide_key_t =
#if _HAS_CXX23
remove_const_t<tuple_element_t<0, typename iterator_traits<_Iter>::value_type>>;
#else // ^^^ C++23 / C++20 vvv
remove_const_t<typename iterator_traits<_Iter>::value_type::first_type>;
#endif // C++20

template <class _Iter>
using _Guide_val_t = typename iterator_traits<_Iter>::value_type::second_type;
using _Guide_val_t =
#if _HAS_CXX23
tuple_element_t<1, typename iterator_traits<_Iter>::value_type>;
#else // ^^^ C++23 / C++20 vvv
typename iterator_traits<_Iter>::value_type::second_type;
#endif // C++20

template <class _Iter>
using _Guide_pair_t = pair<add_const_t<typename iterator_traits<_Iter>::value_type::first_type>,
typename iterator_traits<_Iter>::value_type::second_type>;
using _Guide_pair_t =
#if _HAS_CXX23
pair<add_const_t<tuple_element_t<0, typename iterator_traits<_Iter>::value_type>>,
tuple_element_t<1, typename iterator_traits<_Iter>::value_type>>;
#else // ^^^ C++23 / C++20 vvv
pair<add_const_t<typename iterator_traits<_Iter>::value_type::first_type>,
typename iterator_traits<_Iter>::value_type::second_type>;
#endif // C++20

_EXPORT_STD template <class _Ty>
struct is_execution_policy : false_type {};
Expand Down Expand Up @@ -3595,17 +3611,6 @@ namespace ranges {
};
} // namespace ranges

// These declarations must be visible to qualified name lookup for _STD get in _Pair_like below, even if <tuple> hasn't
// yet been included.
_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr tuple_element_t<_Index, tuple<_Types...>>& get(tuple<_Types...>& _Tuple) noexcept;
_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>& get(const tuple<_Types...>& _Tuple) noexcept;
_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr tuple_element_t<_Index, tuple<_Types...>>&& get(tuple<_Types...>&& _Tuple) noexcept;
_EXPORT_STD template <size_t _Index, class... _Types>
_NODISCARD constexpr const tuple_element_t<_Index, tuple<_Types...>>&& get(const tuple<_Types...>&& _Tuple) noexcept;

JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
namespace ranges {
// clang-format off
template <class _From, class _To>
Expand All @@ -3617,6 +3622,7 @@ namespace ranges {
concept _Convertible_to_non_slicing = convertible_to<_From, _To>
&& !_Uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;

#if !_HAS_CXX23
template <class _Ty>
concept _Pair_like = !is_reference_v<_Ty> && requires(_Ty __t) {
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
typename tuple_size<_Ty>::type;
Expand All @@ -3626,10 +3632,14 @@ namespace ranges {
{ _STD get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Ty>&>;
{ _STD get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Ty>&>;
};
#endif // !_HAS_CXX23

template <class _Ty, class _First, class _Second>
concept _Pair_like_convertible_from = !range<_Ty> && _Pair_like<_Ty>
&& constructible_from<_Ty, _First, _Second>
concept _Pair_like_convertible_from =
#if _HAS_CXX23
!is_reference_v<_Ty> &&
#endif // _HAS_CXX23
!range<_Ty> && _Pair_like<_Ty> && constructible_from<_Ty, _First, _Second>
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
&& _Convertible_to_non_slicing<_First, tuple_element_t<0, _Ty>>
&& convertible_to<_Second, tuple_element_t<1, _Ty>>;
// clang-format on
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,6 @@
// P2077R3 Heterogeneous Erasure Overloads For Associative Containers
// P2136R3 invoke_r()
// P2165R4 Compatibility Between tuple, pair, And tuple-like Objects
// (changes to views::zip and pair only)
// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
// P2186R2 Removing Garbage Collection Support
// P2273R3 constexpr unique_ptr
Expand Down Expand Up @@ -1709,6 +1708,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
#define __cpp_lib_ranges_starts_ends_with 202106L
#define __cpp_lib_ranges_stride 202207L
#define __cpp_lib_ranges_to_container 202202L
#define __cpp_lib_tuple_like 202207L
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
#endif // __cpp_lib_concepts

#define __cpp_lib_spanstream 202106L
Expand Down
5 changes: 5 additions & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,12 @@ tests\P1899R3_views_stride_death
tests\P1951R1_default_arguments_pair_forward_ctor
tests\P2136R3_invoke_r
tests\P2162R2_std_visit_for_derived_classes_from_variant
tests\P2165R4_tuple_like_common_reference
tests\P2165R4_tuple_like_common_type
tests\P2165R4_tuple_like_operations
tests\P2165R4_tuple_like_pair
tests\P2165R4_tuple_like_relational_operators
tests\P2165R4_tuple_like_tuple_members
tests\P2231R1_complete_constexpr_optional_variant
tests\P2273R3_constexpr_unique_ptr
tests\P2278R4_basic_const_iterator
Expand Down
14 changes: 14 additions & 0 deletions tests/std/tests/P0433R2_deduction_guides/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,20 @@ void test_map_or_multimap() {
static_assert(is_same_v<decltype(m15), M<long, char, MyGreater>>);
static_assert(is_same_v<decltype(m16), M<long, char, MyGreater, MyAlloc<CPurr>>>);
static_assert(is_same_v<decltype(m17), M<long, char, less<long>, MyAlloc<CPurr>>>);

{ // Verify changes from P2165R4
using TupleIter = tuple<int, double>*;
static_assert(is_same_v<decltype(M{TupleIter{}, TupleIter{}}), M<int, double>>);

using PairIter = pair<int, float>*;
static_assert(is_same_v<decltype(M{PairIter{}, PairIter{}}), M<int, float>>);

using ArrayIter = array<int, 2>*;
static_assert(is_same_v<decltype(M{ArrayIter{}, ArrayIter{}}), M<int, int>>);

using SubrangeIter = ranges::subrange<int*, int*>*;
static_assert(is_same_v<decltype(M{SubrangeIter{}, SubrangeIter{}}), M<int*, int*>>);
}
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
}

Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2165R4_tuple_like_common_reference/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <array>
#include <ranges>
#include <tuple>
#include <type_traits>
#include <utility>

using namespace std;
using ranges::subrange;

template <class T, class U>
concept CanCommonReference = requires { typename common_reference<T, U>::type; };

template <class T, class U, class Expected>
requires CanCommonReference<T, U>
constexpr bool test_common_reference =
same_as<common_reference_t<T, U>, Expected> && same_as<common_reference_t<U, T>, Expected>;

struct Sentinel {
bool operator==(const auto&) const; // not defined
operator unreachable_sentinel_t() const; // not defined
};

template <>
struct std::common_type<Sentinel, unreachable_sentinel_t> {
using type = unreachable_sentinel_t;
};

template <>
struct std::common_type<unreachable_sentinel_t, Sentinel> {
using type = unreachable_sentinel_t;
};

static_assert(test_common_reference<Sentinel, unreachable_sentinel_t, unreachable_sentinel_t>);

// Test common_reference<tuple, tuple>
static_assert(test_common_reference<tuple<>, tuple<>, tuple<>>);
static_assert(test_common_reference<tuple<char&&>, tuple<const int&>, tuple<int>>);
static_assert(test_common_reference<tuple<int&>, tuple<const int&>, tuple<const int&>>);
static_assert(test_common_reference<tuple<int&>, tuple<int&&>, tuple<const int&>>);
static_assert(test_common_reference<tuple<short, int, long>, tuple<long, int, short>, tuple<long, int, long>>);

// Test common_reference<cvref tuple, cvref tuple>
static_assert(test_common_reference<tuple<>&, tuple<>&&, const tuple<>&>);
static_assert(
test_common_reference<const tuple<int, long>&, volatile tuple<int, long>&, const volatile tuple<int, long>&>);
static_assert(test_common_reference<tuple<int&, const int&&, volatile int&>&,
const tuple<const int&, const int, const int&>, tuple<const int&, int, const volatile int&>>);

// Test common_reference<tuple, tuple-like>, tuple-like is pair
static_assert(test_common_reference<tuple<int, int>, pair<int, int>, tuple<int, int>>);
static_assert(test_common_reference<tuple<int, long>, pair<short, long long>, tuple<int, long long>>);
static_assert(
test_common_reference<tuple<int&, long&&>, pair<const int&, const long&&>, tuple<const int&, const long&&>>);
static_assert(test_common_reference<tuple<short&, const volatile long&&>, pair<volatile int, long>, tuple<int, long>>);

// Test common_reference<cvref tuple, cvref tuple-like>, tuple-like is pair
static_assert(test_common_reference<tuple<int, int>&, pair<int, int>&, tuple<int&, int&>>);
static_assert(test_common_reference<const tuple<int, int>&, const pair<int, int>&, tuple<const int&, const int&>>);
static_assert(
test_common_reference<tuple<int&, long&&>&, const pair<const int&, const long&&>&, tuple<const int&, const long&>>);
static_assert(test_common_reference<const tuple<short&, const volatile long&&>, const pair<volatile int, long>&,
tuple<int, long>>);

// Test common_reference<tuple, tuple-like>, tuple-like is array
static_assert(test_common_reference<tuple<>, array<int, 0>, tuple<>>);
static_assert(test_common_reference<tuple<int>, array<int, 1>, tuple<int>>);
static_assert(test_common_reference<tuple<int, long>, array<int, 2>, tuple<int, long>>);
static_assert(test_common_reference<tuple<short, int&&, const long>, array<int, 3>, tuple<int, int, long>>);
static_assert(test_common_reference<tuple<short&, int&&, const volatile long>, array<int, 3>, tuple<int, int, long>>);

// Test common_reference<cvref tuple&, cvref tuple-like>, tuple-like is array
JMazurkiewicz marked this conversation as resolved.
Show resolved Hide resolved
static_assert(test_common_reference<const tuple<>&, array<int, 0>, tuple<>>);
static_assert(test_common_reference<tuple<int>&, array<int, 1>&, tuple<int&>>);
static_assert(test_common_reference<const tuple<int, long>&&, array<int, 2>&, tuple<const int&, long>>);

// Test common_reference<tuple, tuple-like>, tuple-like is ranges::subrange
static_assert(test_common_reference<tuple<int*, int*>, subrange<int*, int*>, tuple<int*, int*>>);
static_assert(
test_common_reference<tuple<int*, const int*>, subrange<const int*, int*>, tuple<const int*, const int*>>);
static_assert(test_common_reference<tuple<int*, Sentinel>, subrange<int*, unreachable_sentinel_t>,
tuple<int*, unreachable_sentinel_t>>);
static_assert(test_common_reference<tuple<const volatile int*, Sentinel>, subrange<int*, unreachable_sentinel_t>,
tuple<const volatile int*, unreachable_sentinel_t>>);

// Test common_reference<cvref tuple, cvref tuple-like>, tuple-like is ranges::subrange
static_assert(test_common_reference<const tuple<int*, int*>&&, const subrange<int*, int*>, tuple<int*, int*>>);
static_assert(
test_common_reference<const tuple<int*, const int*>&, subrange<const int*, int*>, tuple<const int*, const int*>>);

int main() {} // COMPILE-ONLY
4 changes: 4 additions & 0 deletions tests/std/tests/P2165R4_tuple_like_common_type/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_latest_matrix.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <array>
#include <ranges>
#include <tuple>
#include <type_traits>
#include <utility>

using namespace std;
using ranges::subrange;

template <class T, class U>
concept CanCommonType = requires { typename common_type<T, U>::type; };

template <class T, class U, class Expected>
requires CanCommonType<T, U>
inline constexpr bool test_common_type =
same_as<common_type_t<T, U>, Expected> && same_as<common_type_t<U, T>, Expected>;

struct Sentinel {
bool operator==(const auto&) const; // not defined
operator unreachable_sentinel_t() const; // not defined
};

template <>
struct std::common_type<Sentinel, unreachable_sentinel_t> {
using type = unreachable_sentinel_t;
};

template <>
struct std::common_type<unreachable_sentinel_t, Sentinel> {
using type = unreachable_sentinel_t;
};

static_assert(test_common_type<Sentinel, unreachable_sentinel_t, unreachable_sentinel_t>);

// Test common_type<tuple, tuple>
static_assert(test_common_type<tuple<>, tuple<>, tuple<>>);
static_assert(test_common_type<tuple<char>, tuple<int>, tuple<int>>);
static_assert(test_common_type<tuple<int&>, tuple<const int&>, tuple<int>>);
static_assert(test_common_type<tuple<int&>, tuple<int&&>, tuple<int>>);
static_assert(test_common_type<tuple<short, long, long>, tuple<long, int, short>, tuple<long, long, long>>);

// Test common_reference<cvref tuple, cvref tuple>
static_assert(test_common_type<const tuple<>&, tuple<>&&, tuple<>>);
static_assert(test_common_type<tuple<char>&, const tuple<int>&&, tuple<int>>);
static_assert(test_common_type<tuple<int&>&, tuple<const int&>, tuple<int>>);
static_assert(test_common_type<volatile tuple<int&>&, tuple<int&&>, tuple<int>>);

// Test common_type<tuple, tuple-like>, tuple-like is pair
static_assert(test_common_type<tuple<int, int>, pair<int, int>, tuple<int, int>>);
static_assert(test_common_type<tuple<int, long>, pair<short, long long>, tuple<int, long long>>);
static_assert(test_common_type<tuple<int&, long&&>, pair<const int&, const long&&>, tuple<int, long>>);
static_assert(test_common_type<tuple<short&, const volatile long&&>, pair<volatile int, long>, tuple<int, long>>);

// Test common_type<cvref tuple, cvref tuple-like>, tuple-like is pair
static_assert(test_common_type<const tuple<int, int>&&, volatile pair<int, int>&, tuple<int, int>>);
static_assert(test_common_type<volatile tuple<int, long>&&, const pair<short, long long>&&, tuple<int, long long>>);

// Test common_type<tuple, tuple-like>, tuple-like is array
static_assert(test_common_type<tuple<>, array<int, 0>, tuple<>>);
static_assert(test_common_type<tuple<int>, array<int, 1>, tuple<int>>);
static_assert(test_common_type<tuple<int, long>, array<int, 2>, tuple<int, long>>);
static_assert(test_common_type<tuple<short, int, long>, array<int, 3>, tuple<int, int, long>>);
static_assert(test_common_type<tuple<short&, int&&, const volatile long>, array<int, 3>, tuple<int, int, long>>);

// Test common_type<cvref tuple, cvref tuple-like>, tuple-like is array
static_assert(test_common_type<const tuple<>&&, volatile array<int, 0>&, tuple<>>);
static_assert(test_common_type<const tuple<int>&, volatile array<int, 1>&&, tuple<int>>);

// Test common_type<tuple, tuple-like>, tuple-like is ranges::subrange
static_assert(test_common_type<tuple<int*, int*>, subrange<int*, int*>, tuple<int*, int*>>);
static_assert(test_common_type<tuple<int*, const int*>, subrange<const int*, int*>, tuple<const int*, const int*>>);
static_assert(test_common_type<tuple<int*, Sentinel>, subrange<int*, unreachable_sentinel_t>,
tuple<int*, unreachable_sentinel_t>>);
static_assert(test_common_type<tuple<const volatile int*, Sentinel>, subrange<int*, unreachable_sentinel_t>,
tuple<const volatile int*, unreachable_sentinel_t>>);

// Test common_type<cvref tuple, cvref tuple-like>, tuple-like is ranges::subrange
static_assert(test_common_type<const tuple<int*, int*>&, volatile subrange<int*, int*>&&, tuple<int*, int*>>);
static_assert(test_common_type<volatile tuple<int*, Sentinel>&, const subrange<int*, unreachable_sentinel_t>&&,
tuple<int*, unreachable_sentinel_t>>);

int main() {} // COMPILE-ONLY
4 changes: 4 additions & 0 deletions tests/std/tests/P2165R4_tuple_like_operations/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_latest_matrix.lst
Loading