[libcxx-commits] [libcxx] 3ffc53b - [libc++] Implements concept default_initializable.
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Feb 1 10:13:33 PST 2021
Author: Mark de Wever
Date: 2021-02-01T19:13:24+01:00
New Revision: 3ffc53ba16272b6475ff49c05ab6aa72f7720383
URL: https://github.com/llvm/llvm-project/commit/3ffc53ba16272b6475ff49c05ab6aa72f7720383
DIFF: https://github.com/llvm/llvm-project/commit/3ffc53ba16272b6475ff49c05ab6aa72f7720383.diff
LOG: [libc++] Implements concept default_initializable.
Implements:
- LWG3149 DefaultConstructible should require default initialization
Implements parts of:
- P0898R3 Standard Library Concepts
- P1754 Rename concepts to standard_case for C++20, while we still can
Depends on D91986
Reviewed By: ldionne, #libc
Differential Revision: https://reviews.llvm.org/D93461
Added:
libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp
libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp
Modified:
libcxx/docs/Cxx2aStatusIssuesStatus.csv
libcxx/include/concepts
Removed:
################################################################################
diff --git a/libcxx/docs/Cxx2aStatusIssuesStatus.csv b/libcxx/docs/Cxx2aStatusIssuesStatus.csv
index 55a9d9b4818c..859c52ae2b21 100644
--- a/libcxx/docs/Cxx2aStatusIssuesStatus.csv
+++ b/libcxx/docs/Cxx2aStatusIssuesStatus.csv
@@ -186,7 +186,7 @@
"`3274 <https://wg21.link/LWG3274>`__","Missing feature test macro for ``<span>``\ ","Belfast","",""
"`3276 <https://wg21.link/LWG3276>`__","Class ``split_view::outer_iterator::value_type``\ should inherit from ``view_interface``\ ","Belfast","",""
"`3277 <https://wg21.link/LWG3277>`__","Pre-increment on prvalues is not a requirement of ``weakly_incrementable``\ ","Belfast","",""
-"`3149 <https://wg21.link/LWG3149>`__","``DefaultConstructible``\ should require default initialization","Belfast","",""
+"`3149 <https://wg21.link/LWG3149>`__","``DefaultConstructible``\ should require default initialization","Belfast","|Complete|","13.0"
"","","","",""
"`1203 <https://wg21.link/LWG1203>`__","More useful rvalue stream insertion","Prague","|Complete|","12.0"
"`2859 <https://wg21.link/LWG2859>`__","Definition of *reachable* in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object","Prague","",""
diff --git a/libcxx/include/concepts b/libcxx/include/concepts
index 86e0325c2b10..e245e54d0a36 100644
--- a/libcxx/include/concepts
+++ b/libcxx/include/concepts
@@ -167,6 +167,16 @@ template<class _Tp, class... _Args>
concept constructible_from =
destructible<_Tp> && _VSTD::is_constructible_v<_Tp, _Args...>;
+// [concept.default.init]
+
+template<class _Tp>
+concept __default_initializable = requires { ::new _Tp; };
+
+template<class _Tp>
+concept default_initializable = constructible_from<_Tp> &&
+ requires { _Tp{}; } && __default_initializable<_Tp>;
+
+
#endif //_LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp b/libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp
new file mode 100644
index 000000000000..2a0ebb2076a2
--- /dev/null
+++ b/libcxx/test/std/concepts/concept.default.init/default_initializable.compile.pass.cpp
@@ -0,0 +1,260 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class T>
+// concept default_initializable = constructible_from<T> &&
+// requires { T{}; } &&
+// is-default-initializable<T>;
+
+#include <array>
+#include <concepts>
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <map>
+#include <queue>
+#include <set>
+#include <span>
+#include <stack>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "test_macros.h"
+
+struct Empty {};
+
+struct CtorDefaulted {
+ CtorDefaulted() = default;
+};
+struct CtorDeleted {
+ CtorDeleted() = delete;
+};
+struct DtorDefaulted {
+ ~DtorDefaulted() = default;
+};
+struct DtorDeleted {
+ ~DtorDeleted() = delete;
+};
+
+struct Noexcept {
+ ~Noexcept() noexcept;
+};
+struct NoexceptTrue {
+ ~NoexceptTrue() noexcept(true);
+};
+struct NoexceptFalse {
+ ~NoexceptFalse() noexcept(false);
+};
+
+struct CtorProtected {
+protected:
+ CtorProtected() = default;
+};
+struct CtorPrivate {
+private:
+ CtorPrivate() = default;
+};
+struct DtorProtected {
+protected:
+ ~DtorProtected() = default;
+};
+struct DtorPrivate {
+private:
+ ~DtorPrivate() = default;
+};
+
+template <class T>
+struct NoexceptDependant {
+ ~NoexceptDependant() noexcept(std::is_same_v<T, int>);
+};
+
+struct CtorExplicit {
+ explicit CtorExplicit() = default;
+};
+struct CtorArgument {
+ CtorArgument(int) {}
+};
+struct CtorDefaultArgument {
+ CtorDefaultArgument(int = 0) {}
+};
+struct CtorExplicitDefaultArgument {
+ explicit CtorExplicitDefaultArgument(int = 0) {}
+};
+
+struct Derived : public Empty {};
+
+class Abstract {
+ virtual void foo() = 0;
+};
+
+class AbstractDestructor {
+ virtual ~AbstractDestructor() = 0;
+};
+
+class OperatorNewDeleted {
+ void* operator new(std::size_t) = delete;
+ void operator delete(void* ptr) = delete;
+};
+
+[[maybe_unused]] auto Lambda = [](const int&, int&&, double){};
+
+template<class T>
+void test_not_const()
+{
+ static_assert( std::default_initializable< T>);
+ static_assert(!std::default_initializable<const T>);
+ static_assert( std::default_initializable< volatile T>);
+ static_assert(!std::default_initializable<const volatile T>);
+}
+
+template<class T>
+void test_true()
+{
+ static_assert( std::default_initializable< T>);
+ static_assert( std::default_initializable<const T>);
+ static_assert( std::default_initializable< volatile T>);
+ static_assert( std::default_initializable<const volatile T>);
+}
+
+template<class T>
+void test_false()
+{
+ static_assert(!std::default_initializable< T>);
+ static_assert(!std::default_initializable<const T>);
+ static_assert(!std::default_initializable< volatile T>);
+ static_assert(!std::default_initializable<const volatile T>);
+}
+
+void test()
+{
+ test_not_const<bool>();
+ test_not_const<char>();
+ test_not_const<int>();
+ test_not_const<double>();
+
+ test_false <void>();
+ test_not_const<void*>();
+
+ test_not_const<int*>();
+ test_false <int[]>();
+ test_not_const<int[1]>();
+ test_false <int&>();
+ test_false <int&&>();
+
+ test_true <Empty>();
+
+ test_true <CtorDefaulted>();
+ test_false <CtorDeleted>();
+ test_true <DtorDefaulted>();
+ test_false <DtorDeleted>();
+
+ test_true <Noexcept>();
+ test_true <NoexceptTrue>();
+ test_false <NoexceptFalse>();
+
+ test_false <CtorProtected>();
+ test_false <CtorPrivate>();
+ test_false <DtorProtected>();
+ test_false <DtorPrivate>();
+
+ test_true <NoexceptDependant<int>>();
+ test_false <NoexceptDependant<double>>();
+
+ test_true <CtorExplicit>();
+ test_false <CtorArgument>();
+ test_true <CtorDefaultArgument>();
+ test_true <CtorExplicitDefaultArgument>();
+
+ test_true <Derived>();
+ test_false <Abstract>();
+ test_false <AbstractDestructor>();
+
+ test_true <OperatorNewDeleted>();
+
+ test_true <decltype(Lambda)>();
+ test_not_const<void(*)(const int&)>();
+ test_not_const<void(Empty::*)(const int&) >();
+ test_not_const<void(Empty::*)(const int&) const >();
+ test_not_const<void(Empty::*)(const int&) volatile>();
+ test_not_const<void(Empty::*)(const int&) const volatile>();
+ test_not_const<void(Empty::*)(const int&) &>();
+ test_not_const<void(Empty::*)(const int&) &&>();
+ test_not_const<void(Empty::*)(const int&) noexcept>();
+ test_not_const<void(Empty::*)(const int&) noexcept(true)>();
+ test_not_const<void(Empty::*)(const int&) noexcept(false)>();
+
+ // Sequence containers
+ test_not_const<std::array< int, 0>>();
+ test_not_const<std::array< int, 1>>();
+ test_false <std::array<const int, 1>>();
+ test_not_const<std::array< volatile int, 1>>();
+ test_false <std::array<const volatile int, 1>>();
+ test_true <std::deque< int>>();
+ test_true <std::deque<const int>>();
+ test_true <std::deque< volatile int>>();
+ test_true <std::deque<const volatile int>>();
+ test_true <std::forward_list<int>>();
+ test_true <std::list<int>>();
+ test_true <std::vector<int>>();
+
+ // Associative containers
+ test_true <std::set<int>>();
+ test_true <std::map<int, int>>();
+ test_true <std::multiset<int>>();
+ test_true <std::multimap<int, int>>();
+
+ // Unordered associative containers
+ test_true <std::unordered_set<int>>();
+ test_true <std::unordered_map<int, int>>();
+ test_true <std::unordered_multiset<int>>();
+ test_true <std::unordered_multimap<int, int>>();
+
+ // Container adaptors
+ test_true <std::stack< int>>();
+ test_true <std::stack<const int>>();
+ test_true <std::stack< volatile int>>();
+ test_true <std::stack<const volatile int>>();
+ test_true <std::queue<int>>();
+ test_true <std::priority_queue<int>>();
+
+ test_true <std::span< int>>();
+ test_true <std::span<const int>>();
+ test_true <std::span< volatile int>>();
+ test_true <std::span<const volatile int>>();
+
+ // Strings
+ test_true <std::string>();
+ test_true <std::wstring>();
+ test_true <std::u8string>();
+ test_true <std::u16string>();
+ test_true <std::u32string>();
+
+ // String views
+ test_true <std::string_view>();
+ test_true <std::wstring_view>();
+ test_true <std::u8string_view>();
+ test_true <std::u16string_view>();
+ test_true <std::u32string_view>();
+
+ // Smart pointers
+ test_true <std::unique_ptr<int>>();
+ test_true <std::shared_ptr<int>>();
+ test_true <std::weak_ptr<int>>();
+
+}
+
+// Required for MSVC internal test runner compatibility.
+int main(int, char**) {
+ return 0;
+}
diff --git a/libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp b/libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp
new file mode 100644
index 000000000000..789846e21b24
--- /dev/null
+++ b/libcxx/test/std/concepts/concept.default.init/default_initializable.verify.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class T>
+// concept default_initializable = constructible_from<T> &&
+// requires { T{}; } &&
+// is-default-initializable<T>;
+
+#include <concepts>
+#include <cassert>
+
+#include "test_macros.h"
+
+template<class T>
+concept brace_initializable = requires { T{}; };
+
+void test() {
+ // LWG3149
+ // Changed the concept from constructible_from<T>
+ // to constructible_from<T> &&
+ // requires { T{}; } && is-default-initializable <T>
+ struct S0 { explicit S0() = default; };
+ S0 x0;
+ S0 y0{};
+ static_assert( std::constructible_from<S0>);
+ static_assert( brace_initializable<S0>);
+ LIBCPP_STATIC_ASSERT( std::__default_initializable<S0>);
+ static_assert( std::default_initializable<S0>);
+
+ struct S1 { S0 x; }; // Note: aggregate
+ S1 x1;
+ S1 y1{}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+ static_assert( std::constructible_from<S1>);
+ static_assert(!brace_initializable<S1>);
+ LIBCPP_STATIC_ASSERT( std::__default_initializable<S1>);
+ static_assert(!std::default_initializable<S1>);
+
+ const int x2; // expected-error {{default initialization of an object of const type 'const int'}}
+ const int y2{};
+
+ static_assert( std::constructible_from<const int>);
+ static_assert( brace_initializable<const int>);
+ LIBCPP_STATIC_ASSERT(!std::__default_initializable<const int>);
+ static_assert(!std::default_initializable<const int>);
+
+ const int x3[1]; // expected-error {{default initialization of an object of const type 'const int [1]'}}
+ const int y3[1]{};
+ static_assert( std::constructible_from<const int[1]>);
+ static_assert( brace_initializable<const int[1]>);
+ LIBCPP_STATIC_ASSERT(!std::__default_initializable<const int[1]>);
+ static_assert(!std::default_initializable<const int[1]>);
+
+ // Zero-length array extension
+ const int x4[]; // expected-error {{definition of variable with array type needs an explicit size or an initializer}}
+ const int y4[]{};
+ static_assert(!std::constructible_from<const int[]>);
+ static_assert( brace_initializable<const int[]>);
+ LIBCPP_STATIC_ASSERT(!std::__default_initializable<const int[]>);
+ static_assert(!std::default_initializable<const int[]>);
+}
+
+int main(int, char**) {
+ test();
+
+ return 0;
+}
More information about the libcxx-commits
mailing list