Skip to content

[libc++][type_traits] Implements "A type trait to detect reference binding to temporary" #128649

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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
ab21883
[libc++][type_traits] Implements "A type trait to detect reference bi…
H-G-Hristov Feb 24, 2025
016d341
Address comments
H-G-Hristov Feb 26, 2025
6d25537
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 26, 2025
5ad9e70
Try to fix CI
H-G-Hristov Feb 26, 2025
93742ac
Fixed modules map condition
H-G-Hristov Feb 26, 2025
9e96a81
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 26, 2025
49910a0
Fixed formatting
H-G-Hristov Feb 26, 2025
fbf6650
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 26, 2025
8be8079
Try to fix CI
H-G-Hristov Feb 26, 2025
f4078bf
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 26, 2025
17197b3
Try to fix Apple CI
H-G-Hristov Feb 27, 2025
5064494
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 27, 2025
b92ffcb
Try to fix CI
H-G-Hristov Feb 27, 2025
cba8f24
Fixed formatting
H-G-Hristov Feb 27, 2025
f2c2651
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 27, 2025
a5d6c89
Try to fix Android
H-G-Hristov Feb 27, 2025
8cf7d8a
Merge branch 'hgh/libcxx/P2255R2-A_type_trait_to_detect_reference_bin…
H-G-Hristov Feb 27, 2025
5446525
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 27, 2025
348efc5
Merge branch 'llvm:main' into hgh/libcxx/P2255R2-A_type_trait_to_dete…
H-G-Hristov Feb 27, 2025
3e46e48
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 27, 2025
3372938
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
b3f16dd
Addressed review comments
H-G-Hristov Feb 28, 2025
4b10d27
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
4edecb2
Try to fix CI
H-G-Hristov Feb 28, 2025
665d81b
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
1d26b11
Merge branch 'hgh/libcxx/P2255R2-A_type_trait_to_detect_reference_bin…
H-G-Hristov Feb 28, 2025
c57704c
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
a8de754
Minor tweaks
H-G-Hristov Feb 28, 2025
8cec474
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
d0e0416
Fixed formatting
H-G-Hristov Feb 28, 2025
03706dd
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
0f34c04
Enable ANDROID
H-G-Hristov Feb 28, 2025
5147b27
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
afc11c6
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
2c717ea
Updated tests
H-G-Hristov Feb 28, 2025
91f9469
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
65993fe
Fix C++03
H-G-Hristov Feb 28, 2025
90f3f52
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Feb 28, 2025
530980f
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
Zingam Mar 2, 2025
deb90e9
Fixed type in macro name
H-G-Hristov Mar 3, 2025
b9e1bfb
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 3, 2025
69b6b61
Android NDK r29 support + Release Notes
H-G-Hristov Mar 5, 2025
38b7bc0
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 5, 2025
994d163
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 6, 2025
65ebe1e
Updated macros to handle ANDROID clearer
H-G-Hristov Mar 6, 2025
a1e77d2
Addressed review comments
H-G-Hristov Mar 6, 2025
bd63cfc
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 6, 2025
d192d7f
Addressed review comments
H-G-Hristov Mar 6, 2025
28373d2
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 6, 2025
0e25010
Fix CI
H-G-Hristov Mar 6, 2025
9342360
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 6, 2025
ae76e7a
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 7, 2025
d50473d
Review comments
H-G-Hristov Mar 7, 2025
ad90ac1
Merge branch 'main' into hgh/libcxx/P2255R2-A_type_trait_to_detect_re…
H-G-Hristov Mar 7, 2025
67274bb
Renamed types
H-G-Hristov Mar 7, 2025
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
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/21.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Implemented Papers
- N4258: Cleaning-up noexcept in the Library (`Github <https://github.com/llvm/llvm-project/issues/99937>`__)
- P0767R1: Deprecate POD (`Github <https://github.com/llvm/llvm-project/issues/104013>`__)
- P1361R2: Integration of chrono with text formatting (`Github <https://github.com/llvm/llvm-project/issues/100014>`__)
- P2255R2: A type trait to detect reference binding to temporary (implemented the type traits only) (`Github <https://github.com/llvm/llvm-project/issues/105180>`)

Improvements and New Features
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"`P0627R6 <https://wg21.link/P0627R6>`__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15",""
"`P1206R7 <https://wg21.link/P1206R7>`__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17",""
"`P1413R3 <https://wg21.link/P1413R3>`__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations."
"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","","",""
"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","Implemented the type traits only."
"`P2273R3 <https://wg21.link/P2273R3>`__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16",""
"`P2387R3 <https://wg21.link/P2387R3>`__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19",""
"`P2440R1 <https://wg21.link/P2440R1>`__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","","",""
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,8 @@ set(files
__type_traits/negation.h
__type_traits/promote.h
__type_traits/rank.h
__type_traits/reference_constructs_from_temporary.h
__type_traits/reference_converts_from_temporary.h
__type_traits/remove_all_extents.h
__type_traits/remove_const.h
__type_traits/remove_const_ref.h
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// 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 _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H
#define _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H

#include <__config>
#include <__type_traits/integral_constant.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)

template <class _Tp, class _Up>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS reference_constructs_from_temporary
: public bool_constant<__reference_constructs_from_temporary(_Tp, _Up)> {};

template <class _Tp, class _Up>
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_temporary_v =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zingam It looks like you forgot to add tests for the _LIBCPP_NO_SPECIALIZATIONS annotations. Could you add them in a follow-up PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'll do it.

__reference_constructs_from_temporary(_Tp, _Up);

#endif

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// 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 _LIBCPP___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARY_H
#define _LIBCPP___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARY_H

#include <__config>
#include <__type_traits/integral_constant.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_converts_from_temporary)

template <class _Tp, class _Up>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS reference_converts_from_temporary
: public bool_constant<__reference_converts_from_temporary(_Tp, _Up)> {};

template <class _Tp, class _Up>
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_converts_from_temporary_v =
__reference_converts_from_temporary(_Tp, _Up);

#endif

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARY_H
8 changes: 8 additions & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,14 @@ module std_core [system] {
module negation { header "__type_traits/negation.h" }
module promote { header "__type_traits/promote.h" }
module rank { header "__type_traits/rank.h" }
module reference_constructs_from_temporary {
header "__type_traits/reference_constructs_from_temporary.h"
export std_core.type_traits.integral_constant
}
module reference_converts_from_temporary {
header "__type_traits/reference_converts_from_temporary.h"
export std_core.type_traits.integral_constant
}
module remove_all_extents { header "__type_traits/remove_all_extents.h" }
module remove_const_ref { header "__type_traits/remove_const_ref.h" }
module remove_const { header "__type_traits/remove_const.h" }
Expand Down
11 changes: 11 additions & 0 deletions libcxx/include/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ namespace std

template<class T> struct has_unique_object_representations; // C++17

template<class T, class U> struct reference_constructs_from_temporary; // Since C++23
template<class T, class U> struct reference_converts_from_temporary; // Since C++23

// Relationships between types:
template <class T, class U> struct is_same;
template <class Base, class Derived> struct is_base_of;
Expand Down Expand Up @@ -382,6 +385,12 @@ namespace std
= has_virtual_destructor<T>::value; // C++17
template<class T> inline constexpr bool has_unique_object_representations_v // C++17
= has_unique_object_representations<T>::value;
template<class T, class U>
constexpr bool reference_constructs_from_temporary_v
= reference_constructs_from_temporary<T, U>::value; // Since C++23
template<class T, class U>
constexpr bool reference_converts_from_temporary_v
= reference_converts_from_temporary<T, U>::value; // Since C++23

// See C++14 20.10.5, type property queries
template <class T> inline constexpr size_t alignment_of_v
Expand Down Expand Up @@ -523,6 +532,8 @@ namespace std

# if _LIBCPP_STD_VER >= 23
# include <__type_traits/is_implicit_lifetime.h>
# include <__type_traits/reference_constructs_from_temporary.h>
# include <__type_traits/reference_converts_from_temporary.h>
# endif

# include <version>
Expand Down
20 changes: 16 additions & 4 deletions libcxx/modules/std/type_traits.inc
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,14 @@ export namespace std {

using std::has_unique_object_representations;

// using std::reference_constructs_from_temporary;
// using std::reference_converts_from_temporary;
#if _LIBCPP_STD_VER >= 23
# if __has_builtin(__reference_constructs_from_temporary)
using std::reference_constructs_from_temporary;
# endif
# if __has_builtin(__reference_converts_from_temporary)
using std::reference_converts_from_temporary;
# endif
#endif

// [meta.unary.prop.query], type property queries
using std::alignment_of;
Expand Down Expand Up @@ -284,8 +290,14 @@ export namespace std {
using std::is_unbounded_array_v;
using std::is_unsigned_v;
using std::is_volatile_v;
// using std::reference_constructs_from_temporary_v;
// using std::reference_converts_from_temporary_v;
#if _LIBCPP_STD_VER >= 23
# if __has_builtin(__reference_constructs_from_temporary)
using std::reference_constructs_from_temporary_v;
# endif
# if __has_builtin(__reference_converts_from_temporary)
using std::reference_converts_from_temporary_v;
# endif
#endif

// [meta.unary.prop.query], type property queries
using std::alignment_of_v;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,52 @@ struct A {
A& operator=(const A&);
};

class Abstract
{
virtual ~Abstract() = 0;
class Abstract {
virtual ~Abstract() = 0;
};

// Types for reference_{constructs/converts}_from_temporary

#if TEST_STD_VER >= 23

class NonPODClass {
public:
NonPODClass(int);
};
enum Enum { EV };
struct Base {
Enum e;
int i;
float f;
NonPODClass* p;
};
// Not PODs
struct Derived : Base {};

template <class T, class RefType = T&>
class ConvertsToRef {
public:
operator RefType() const { return static_cast<RefType>(obj); }
mutable T obj = 42;
};
template <class T, class RefType = T&>
class ConvertsToRefPrivate {
operator RefType() const { return static_cast<RefType>(obj); }
mutable T obj = 42;
};

class ExplicitConversionRvalueRef {
public:
operator int();
explicit operator int&&();
};

class ExplicitConversionRef {
public:
operator int();
explicit operator int&();
};

#endif

#endif // TEST_META_UNARY_COMP_COMMON_H
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// These compilers don't support __builtin_is_implicit_lifetime yet.
// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16

// <type_traits>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// These compilers don't support __builtin_is_implicit_lifetime yet.
// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16

// <type_traits>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// REQUIRES: std-at-least-c++23

// These compilers don't support std::reference_converts_from_temporary yet.
// UNSUPPORTED: android, apple-clang-15, apple-clang-16, clang-19.1

// <type_traits>

// template<class T, class U> struct reference_constructs_from_temporary;

// template<class T, class U>
// constexpr bool reference_constructs_from_temporary_v
// = reference_constructs_from_temporary<T, U>::value;

#include <cassert>
#include <type_traits>

#include "common.h"
#include "test_macros.h"

template <typename T, typename U, bool Expected>
constexpr void test_reference_constructs_from_temporary() {
assert((std::reference_constructs_from_temporary<T, U>::value == Expected));
assert((std::reference_constructs_from_temporary_v<T, U> == Expected));
}

constexpr bool test() {
test_reference_constructs_from_temporary<int&, int&, false>();
test_reference_constructs_from_temporary<int&, int&, false>();
test_reference_constructs_from_temporary<int&, int&&, false>();

test_reference_constructs_from_temporary<const int&, int&, false>();
test_reference_constructs_from_temporary<const int&, const int&, false>();
test_reference_constructs_from_temporary<const int&, int&&, false>();

test_reference_constructs_from_temporary<int&, long&, false>(); // doesn't construct

test_reference_constructs_from_temporary<const int&, long&, true>();
test_reference_constructs_from_temporary<const int&, long&&, true>();
test_reference_constructs_from_temporary<int&&, long&, true>();

assert((std::is_constructible_v<int&, ConvertsToRef<int, int&>>));
test_reference_constructs_from_temporary<int&, ConvertsToRef<int, int&>, false>();

assert((std::is_constructible_v<int&&, ConvertsToRef<int, int&&>>));
test_reference_constructs_from_temporary<int&&, ConvertsToRef<int, int&&>, false>();

assert((std::is_constructible_v<const int&, ConvertsToRef<int, const int&>>));
test_reference_constructs_from_temporary<int&&, ConvertsToRef<int, const int&>, false>();

assert((std::is_constructible_v<const int&, ConvertsToRef<long, long&>>));
test_reference_constructs_from_temporary<const int&, ConvertsToRef<long, long&>, true>();
#ifndef TEST_COMPILER_GCC
test_reference_constructs_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
#endif

// Test that it doesn't accept non-reference types as input.
test_reference_constructs_from_temporary<int, long, false>();

test_reference_constructs_from_temporary<const int&, long, true>();

// Additional checks
test_reference_constructs_from_temporary<const Base&, Derived, true>();
test_reference_constructs_from_temporary<int&&, int, true>();
test_reference_constructs_from_temporary<const int&, int, true>();
test_reference_constructs_from_temporary<int&&, int&&, false>();
test_reference_constructs_from_temporary<const int&, int&&, false>();
test_reference_constructs_from_temporary<int&&, long&&, true>();
test_reference_constructs_from_temporary<int&&, long, true>();

test_reference_constructs_from_temporary<int&, ExplicitConversionRef, false>();
test_reference_constructs_from_temporary<const int&, ExplicitConversionRef, false>();
test_reference_constructs_from_temporary<int&&, ExplicitConversionRvalueRef, false>();

return true;
}

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

return 0;
}
Loading
Loading