[libcxx-commits] [libcxx] 6d9dfd7 - [libc++][type_traits] Implements "A type trait to detect reference binding to temporary" (#128649)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Mar 8 06:21:00 PST 2025
Author: Hristo Hristov
Date: 2025-03-08T15:20:56+01:00
New Revision: 6d9dfd75e4df9fdff9ea34f1c0bd741bf5b53b89
URL: https://github.com/llvm/llvm-project/commit/6d9dfd75e4df9fdff9ea34f1c0bd741bf5b53b89
DIFF: https://github.com/llvm/llvm-project/commit/6d9dfd75e4df9fdff9ea34f1c0bd741bf5b53b89.diff
LOG: [libc++][type_traits] Implements "A type trait to detect reference binding to temporary" (#128649)
Implements partially: [P2255R2: A type trait to detect reference binding
to temporary](https://wg21.link/P2255R2)
Issue: https://github.com/llvm/llvm-project/issues/105180
https://eel.is/c++draft/meta.type.synop
https://eel.is/c++draft/meta.unary.prop
Implented type traits:
- [x] `reference_constructs_from_temporary`
- [x] `reference_converts_from_temporary`
Closes #129049
Minor drive-by tweak to `std::is_implicit_lifetime` tests.
---------
Co-authored-by: Hristo Hristov <zingam at outlook.com>
Added:
libcxx/include/__type_traits/reference_constructs_from_temporary.h
libcxx/include/__type_traits/reference_converts_from_temporary.h
libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
Modified:
libcxx/docs/ReleaseNotes/21.rst
libcxx/docs/Status/Cxx23Papers.csv
libcxx/include/CMakeLists.txt
libcxx/include/module.modulemap
libcxx/include/type_traits
libcxx/modules/std/type_traits.inc
libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index c45adbaec3953..a1100f0630382 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -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
-----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index bfaa63a7c224e..0f3db57788b49 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -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)","","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index ee1d7b872b364..d7c36d6b438fb 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -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
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
new file mode 100644
index 0000000000000..1666032b89bed
--- /dev/null
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -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 =
+ __reference_constructs_from_temporary(_Tp, _Up);
+
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
new file mode 100644
index 0000000000000..043bdbf38dada
--- /dev/null
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -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
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 81c7378d9e3b8..b9964dac84acd 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -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" }
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 772e4cb876469..e09a911eeb313 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -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;
@@ -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
@@ -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>
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index f544f95c7aaaa..6823c86ed153b 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -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;
@@ -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;
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
index be9149de89a6c..b51444915a5c5 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
@@ -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
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
index 681ad13a07dfd..24adec37431e7 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
@@ -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>
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
index 34462f9bf0ec6..4bcb10d0b7579 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
@@ -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>
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
new file mode 100644
index 0000000000000..5b3753c67381f
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -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;
+}
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
new file mode 100644
index 0000000000000..849e286c8cdab
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
@@ -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-18, clang-19.1
+
+// <type_traits>
+
+// template<class T, class U> struct reference_converts_from_temporary;
+
+// template<class T, class U>
+// constexpr bool reference_converts_from_temporary_v
+// = reference_converts_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_converts_from_temporary() {
+ assert((std::reference_converts_from_temporary<T, U>::value == Expected));
+ assert((std::reference_converts_from_temporary_v<T, U> == Expected));
+}
+
+constexpr bool test() {
+ test_reference_converts_from_temporary<int&, int&, false>();
+ test_reference_converts_from_temporary<int&, int&, false>();
+ test_reference_converts_from_temporary<int&, int&&, false>();
+
+ test_reference_converts_from_temporary<const int&, int&, false>();
+ test_reference_converts_from_temporary<const int&, const int&, false>();
+ test_reference_converts_from_temporary<const int&, int&&, false>();
+
+ test_reference_converts_from_temporary<int&, long&, false>(); // doesn't construct
+
+ test_reference_converts_from_temporary<const int&, long&, true>();
+ test_reference_converts_from_temporary<const int&, long&&, true>();
+ test_reference_converts_from_temporary<int&&, long&, true>();
+
+ assert((std::is_constructible_v<int&, ConvertsToRef<int, int&>>));
+ test_reference_converts_from_temporary<int&, ConvertsToRef<int, int&>, false>();
+
+ assert((std::is_constructible_v<int&&, ConvertsToRef<int, int&&>>));
+ test_reference_converts_from_temporary<int&&, ConvertsToRef<int, int&&>, false>();
+
+ assert((std::is_constructible_v<const int&, ConvertsToRef<int, const int&>>));
+ test_reference_converts_from_temporary<int&&, ConvertsToRef<int, const int&>, false>();
+
+ assert((std::is_constructible_v<const int&, ConvertsToRef<long, long&>>));
+ test_reference_converts_from_temporary<const int&, ConvertsToRef<long, long&>, true>();
+#ifndef TEST_COMPILER_GCC
+ test_reference_converts_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
+#endif
+
+ // Test that it doesn't accept non-reference types as input.
+ test_reference_converts_from_temporary<int, long, false>();
+
+ test_reference_converts_from_temporary<const int&, long, true>();
+
+ // Additional checks
+ test_reference_converts_from_temporary<const Base&, Derived, true>();
+ test_reference_converts_from_temporary<int&&, int, true>();
+ test_reference_converts_from_temporary<const int&, int, true>();
+ test_reference_converts_from_temporary<int&&, int&&, false>();
+ test_reference_converts_from_temporary<const int&, int&&, false>();
+ test_reference_converts_from_temporary<int&&, long&&, true>();
+ test_reference_converts_from_temporary<int&&, long, true>();
+
+ test_reference_converts_from_temporary<int&, ExplicitConversionRef, false>();
+ test_reference_converts_from_temporary<const int&, ExplicitConversionRef, true>();
+ test_reference_converts_from_temporary<int&&, ExplicitConversionRvalueRef, true>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
More information about the libcxx-commits
mailing list