Skip to content

[libc++][variant] P2637R3: Member visit (std::variant) #76447

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

Merged
merged 43 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
f8c52dc
[libc++][variant] P2637R3 - Member visit
Zingam Dec 18, 2023
c216ed8
Merge branch 'main' into task/hgh/P2637R3-member-visit
Zingam Dec 21, 2023
1310b54
Merge branch 'main' into task/hgh/P2637R3-member-visit
Zingam Dec 21, 2023
68075dd
WIP: Test via macro
Zingam Dec 24, 2023
0bc0832
WIP: visit.pass
Zingam Dec 24, 2023
1de898e
template_argument
Zingam Dec 24, 2023
a52349b
Implemented missing `visit` constraint + test
Zingam Dec 25, 2023
9b7064d
WIP: Updated visit tests
Zingam Dec 27, 2023
2d47529
WIP: tests
Zingam Dec 27, 2023
55516cd
WIP: more test refactoring
Zingam Dec 27, 2023
5097751
Completed: visit_return_type.pass
Zingam Dec 27, 2023
653ec7a
Syn cleanup
Zingam Dec 27, 2023
9126f03
Fixed formatting
Zingam Dec 27, 2023
ae8a8d6
Restored original files
Zingam Dec 30, 2023
4d3ff8b
Renamed files and cleanup
Zingam Dec 30, 2023
78f5d3e
Fixed: member.visit_return_type.pass.cpp
Zingam Dec 30, 2023
1bcbb51
Fixed: member.visit.pass.cpp
Zingam Dec 30, 2023
5df0fea
Formatted: visit.return_type.pass.cpp and visit.robust_against_adl.pa…
Zingam Dec 30, 2023
8eaaa41
Addressed comments
Zingam Dec 31, 2023
8f43a47
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
Zingam Dec 31, 2023
38e8f43
Removed test case
Zingam Dec 31, 2023
6de98f3
Addressed comment
Zingam Dec 31, 2023
759e0d5
WIP: Experiment with forward declaration
Zingam Dec 31, 2023
0a99bd9
Used forward declaration: `std::visit`
Zingam Dec 31, 2023
ed7bc12
Moved member `visit` to a separate folder.
Zingam Jan 1, 2024
ec32eb5
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
Zingam Jan 1, 2024
fde8ea9
Applied frederick-vs-ja's suggestion
Zingam Jan 3, 2024
47b09d3
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
Zingam Jan 17, 2024
989203e
Try to fix CI
Zingam Jan 17, 2024
668f337
Try to fix CI
Zingam Jan 17, 2024
06a2402
Fix CI on AIX and Arm
Zingam Jan 18, 2024
3d760da
Try to fix CI
Zingam Jan 18, 2024
b2ced9e
Try to fix CI on AIX
Zingam Jan 18, 2024
9c52e75
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
H-G-Hristov Jan 18, 2024
059b150
Addressed comments
Zingam Jan 18, 2024
376657c
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
H-G-Hristov Jan 18, 2024
c0dc054
Defined `_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER`
Zingam Jan 20, 2024
3bff454
Unsupport tests on *apple-clang*
Zingam Jan 20, 2024
edcdc37
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
Zingam Jan 20, 2024
8376b45
Fix the mistake
Zingam Jan 20, 2024
e68fe51
Fixed formatting
Zingam Jan 20, 2024
c056e69
Merge branch 'main' into hgh/libcxx/P2637R3-member-visit-variant
H-G-Hristov Jan 20, 2024
fa2cb78
Addressed comments
Zingam Jan 20, 2024
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
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"`P0792R14 <https://wg21.link/P0792R14>`__","LWG","``function_ref``: a type-erased callable reference","Varna June 2023","","",""
"`P2874R2 <https://wg21.link/P2874R2>`__","LWG","Mandating Annex D Require No More","Varna June 2023","","",""
"`P2757R3 <https://wg21.link/P2757R3>`__","LWG","Type-checking format args","Varna June 2023","","","|format|"
"`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","","","|format|"
"`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","|Partial|","18.0",""
"`P2641R4 <https://wg21.link/P2641R4>`__","CWG, LWG","Checking if a ``union`` alternative is active","Varna June 2023","","",""
"`P1759R6 <https://wg21.link/P1759R6>`__","LWG","Native handles and file streams","Varna June 2023","|Complete|","18.0",""
"`P2697R1 <https://wg21.link/P2697R1>`__","LWG","Interfacing ``bitset`` with ``string_view``","Varna June 2023","|Complete|","18.0",""
Expand Down
5 changes: 5 additions & 0 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,11 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c
# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
# endif

// Clang-18 has support for deducing this, but it does not set the FTM.
# if defined(__cpp_explicit_this_parameter) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1800)
# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
# endif

#endif // __cplusplus

#endif // _LIBCPP___CONFIG
48 changes: 43 additions & 5 deletions libcxx/include/variant
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ namespace std {

// 20.7.2.6, swap
void swap(variant&) noexcept(see below);

// [variant.visit], visitation
template<class Self, class Visitor>
constexpr decltype(auto) visit(this Self&&, Visitor&&); // Since C++26
template<class R, class Self, class Visitor>
constexpr R visit(this Self&&, Visitor&&); // Since C++26
};

// 20.7.3, variant helper classes
Expand Down Expand Up @@ -235,6 +241,7 @@ namespace std {
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <__utility/forward_like.h>
#include <__utility/in_place.h>
#include <__utility/move.h>
#include <__utility/swap.h>
Expand Down Expand Up @@ -1130,6 +1137,19 @@ using __best_match_t = typename invoke_result_t<_MakeOverloads<_Types...>, _Tp,

} // namespace __variant_detail

template <class _Visitor, class... _Vs, typename = void_t<decltype(std::__as_variant(std::declval<_Vs>()))...>>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr decltype(auto)
visit(_Visitor&& __visitor, _Vs&&... __vs);

# if _LIBCPP_STD_VER >= 20
template <class _Rp,
class _Visitor,
class... _Vs,
typename = void_t<decltype(std::__as_variant(std::declval<_Vs>()))...>>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Rp
visit(_Visitor&& __visitor, _Vs&&... __vs);
# endif

template <class... _Types>
class _LIBCPP_TEMPLATE_VIS _LIBCPP_DECLSPEC_EMPTY_BASES variant
: private __sfinae_ctor_base< __all<is_copy_constructible_v<_Types>...>::value,
Expand Down Expand Up @@ -1273,6 +1293,27 @@ public:
__impl_.__swap(__that.__impl_);
}

# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
// Helper class to implement [variant.visit]/10
// Constraints: The call to visit does not use an explicit template-argument-list
// that begins with a type template-argument.
struct __variant_visit_barrier_tag {
_LIBCPP_HIDE_FROM_ABI explicit __variant_visit_barrier_tag() = default;
};

template <__variant_visit_barrier_tag = __variant_visit_barrier_tag{}, class _Self, class _Visitor>
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) visit(this _Self&& __self, _Visitor&& __visitor) {
using _VariantT = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, variant>>;
return std::visit(std::forward<_Visitor>(__visitor), (_VariantT)__self);
}

template <class _Rp, class _Self, class _Visitor>
_LIBCPP_HIDE_FROM_ABI constexpr _Rp visit(this _Self&& __self, _Visitor&& __visitor) {
using _VariantT = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, variant>>;
return std::visit<_Rp>(std::forward<_Visitor>(__visitor), (_VariantT)__self);
}
# endif

private:
__variant_detail::__impl<_Types...> __impl_;

Expand Down Expand Up @@ -1511,7 +1552,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr vo
}
}

template < class _Visitor, class... _Vs, typename = void_t<decltype(std::__as_variant(std::declval<_Vs>()))...> >
template < class _Visitor, class... _Vs, typename>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr decltype(auto)
visit(_Visitor&& __visitor, _Vs&&... __vs) {
using __variant_detail::__visitation::__variant;
Expand All @@ -1520,10 +1561,7 @@ visit(_Visitor&& __visitor, _Vs&&... __vs) {
}

# if _LIBCPP_STD_VER >= 20
template < class _Rp,
class _Visitor,
class... _Vs,
typename = void_t<decltype(std::__as_variant(std::declval<_Vs>()))...> >
template < class _Rp, class _Visitor, class... _Vs, typename>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Rp
visit(_Visitor&& __visitor, _Vs&&... __vs) {
using __variant_detail::__visitation::__variant;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
// The tested functionality needs deducing this.
// UNSUPPORTED: clang-16 || clang-17
// XFAIL: apple-clang

// <variant>

// class variant;
// template<class Self, class Visitor>
// constexpr decltype(auto) visit(this Self&&, Visitor&&); // since C++26
// template<class R, class Self, class Visitor>
// constexpr R visit(this Self&&, Visitor&&); // since C++26

#include <variant>

#include "test_macros.h"

struct Incomplete;
template <class T>
struct Holder {
T t;
};

constexpr bool test(bool do_it) {
if (do_it) {
std::variant<Holder<Incomplete>*, int> v = nullptr;

v.visit([](auto) {});
v.visit([](auto) -> Holder<Incomplete>* { return nullptr; });
v.visit<void>([](auto) {});
v.visit<void*>([](auto) -> Holder<Incomplete>* { return nullptr; });
}
return true;
}

int main(int, char**) {
test(true);
static_assert(test(true));

return 0;
}
Loading