[libcxx-commits] [libcxx] [libc++] P2641R4: Checking if a `union` alternative is active (`std::is_within_lifetime`) (PR #107450)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Sep 10 06:49:18 PDT 2024
================
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <type_traits>
+
+// template <class T>
+// consteval bool is_within_lifetime(const T*) noexcept; // C++26
+
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+#ifndef __cpp_lib_is_within_lifetime
+
+// Check that it doesn't exist if the feature test macro isn't defined (via ADL)
+template <class T>
+constexpr decltype(static_cast<void>(is_within_lifetime(std::declval<T>())), bool{}) is_within_lifetime_exists(int) {
+ return true;
+}
+template <class T>
+constexpr bool is_within_lifetime_exists(long) {
+ return false;
+}
+
+static_assert(!is_within_lifetime_exists<const std::integral_constant<bool, false>*>(0), "");
+
+#elif TEST_STD_VER < 26
+# error __cpp_lib_is_within_lifetime defined before C++26
+#else // defined(__cpp_lib_is_within_lifetime) && TEST_STD_VER >= 26
+
+ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<int*>())), bool);
+ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<const int*>())), bool);
+ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<void*>())), bool);
+ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<const void*>())), bool);
+
+ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<int*>()));
+ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<const int*>()));
+ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<void*>()));
+ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<const void*>()));
+
+template <class T>
+concept is_within_lifetime_exists = requires(T t) { std::is_within_lifetime(t); };
+
+struct S {};
+
+static_assert(is_within_lifetime_exists<int*>);
+static_assert(is_within_lifetime_exists<const int*>);
+static_assert(is_within_lifetime_exists<void*>);
+static_assert(is_within_lifetime_exists<const void*>);
+static_assert(!is_within_lifetime_exists<int>); // Not a pointer
+static_assert(!is_within_lifetime_exists<decltype(nullptr)>); // Not a pointer
+static_assert(!is_within_lifetime_exists<void() const>); // Not a pointer
+static_assert(!is_within_lifetime_exists<int S::*>); // Doesn't accept pointer-to-member
+static_assert(!is_within_lifetime_exists<void (S::*)()>);
+static_assert(!is_within_lifetime_exists<void (*)()>); // Doesn't match `const T*`
+
+constexpr int i = 0;
----------------
ldionne wrote:
I would write these tests like this instead, for readability:
```
consteval bool test() {
// short comment explaining what you're testing
{
constexpr int i = 0;
assert(std::is_within_lifetime(&i));
assert(std::is_within_lifetime(const_cast<int*>(&i)));
assert(std::is_within_lifetime(static_cast<const void*>(&i)));
assert(std::is_within_lifetime(static_cast<void*>(const_cast<int*>(&i))));
assert(std::is_within_lifetime<const int>(&i));
assert(std::is_within_lifetime<int>(const_cast<int*>(&i)));
assert(std::is_within_lifetime<const void>(static_cast<const void*>(&i)));
assert(std::is_within_lifetime<void>(static_cast<void*>(const_cast<int*>(&i))));
}
// short comment explaining what you're testing
{
constexpr union {
int active;
int inactive;
} u{.active = 1};
assert(std::is_within_lifetime(&u.active));
assert(!std::is_within_lifetime(&u.inactive));
}
// short comment explaining what you're testing
{
union {
int active;
int inactive;
};
assert(!std::is_within_lifetime(&active));
assert(!std::is_within_lifetime(&inactive));
active = 1;
assert(std::is_within_lifetime(&active));
assert(!std::is_within_lifetime(&inactive));
inactive = 1;
assert(!std::is_within_lifetime(&active));
assert(std::is_within_lifetime(&inactive));
}
// short comment explaining what you're testing
{
int j;
S s;
assert(std::is_within_lifetime(&j));
assert(std::is_within_lifetime(&s));
}
return true;
}
static_assert(test());
```
https://github.com/llvm/llvm-project/pull/107450
More information about the libcxx-commits
mailing list