Skip to content
This repository was archived by the owner on Mar 22, 2023. It is now read-only.

Commit bad9b97

Browse files
authored
Merge pull request #1158 from karczex/array-cpp20
[array] add c++20 initialization_list constructor
2 parents 433d174 + afa93e0 commit bad9b97

File tree

11 files changed

+257
-68
lines changed

11 files changed

+257
-68
lines changed

include/libpmemobj++/container/array.hpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: BSD-3-Clause
2-
/* Copyright 2018-2020, Intel Corporation */
2+
/* Copyright 2018-2021, Intel Corporation */
33

44
/**
55
* @file
@@ -11,6 +11,7 @@
1111

1212
#include <algorithm>
1313
#include <functional>
14+
#include <initializer_list>
1415

1516
#include <libpmemobj++/container/detail/contiguous_iterator.hpp>
1617
#include <libpmemobj++/detail/common.hpp>
@@ -41,6 +42,15 @@ namespace obj
4142
*
4243
* When a non-const iterator is returned it adds part of the array
4344
* to a transaction while traversing.
45+
*
46+
* @note According to changes in C++ standard, pmem::obj::array is not an
47+
* aggregate since C++20.
48+
*
49+
* @note Since C++20 pmem::obj::array cannot be initialized via constructor for
50+
* types with deleted copy constructor. This may change in the future.
51+
*
52+
* @note Since C++20 pmem::obj::array for const types can be initialized only
53+
* via default constructor. This may change in the future.
4454
*/
4555
template <typename T, std::size_t N>
4656
struct array {
@@ -98,6 +108,25 @@ struct array {
98108
*/
99109
array(array &&) = default;
100110

111+
#if __cplusplus > 201703L
112+
/**
113+
* Constructor taking std::initializer_list.
114+
*
115+
* It provides similar initialization semantics for
116+
* C++20 (where pmem::obj::array is no longer an aggregate).
117+
*/
118+
array(std::initializer_list<T> list)
119+
{
120+
if constexpr (N > 0) {
121+
size_t i = 0;
122+
for (auto &v : list) {
123+
(*this)[i] = v;
124+
i++;
125+
}
126+
}
127+
}
128+
#endif /* __cplusplus */
129+
101130
/**
102131
* Copy assignment operator - perform assignment from other
103132
* pmem::obj::array.

tests/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ if(TEST_ARRAY)
354354
add_test_generic(NAME array_slice_pmreorder CASE 0 TRACERS none SCRIPT array/array_slice_pmreorder_0.cmake)
355355
add_test_generic(NAME array_slice_pmreorder CASE 1 TRACERS none SCRIPT array/array_slice_pmreorder_1.cmake)
356356
endif()
357+
if(CXX_STANDARD GREATER 14)
358+
build_test(array_is_aggregate array/array_is_aggregate.cpp)
359+
add_test_generic(NAME array_is_aggregate TRACERS none)
360+
endif()
357361
endif()
358362
################################################################################
359363
###################################### VECTOR ##################################

tests/array/array_is_aggregate.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/* Copyright 2021, Intel Corporation */
3+
4+
#include "unittest.hpp"
5+
6+
#include <libpmemobj++/container/array.hpp>
7+
8+
/* Test which checks if array behave in the same way as any structure with
9+
* defaulted constructor - according to used c++ standard */
10+
struct struct_with_defaulted_constructor {
11+
struct_with_defaulted_constructor() = default;
12+
};
13+
14+
int
15+
main()
16+
{
17+
bool array_is_aggregate =
18+
std::is_aggregate<pmem::obj::array<int, 1>>::value;
19+
bool cpp_standard_support =
20+
std::is_aggregate<struct_with_defaulted_constructor>::value;
21+
22+
UT_ASSERTeq(array_is_aggregate, cpp_standard_support);
23+
}

tests/common/helper_classes.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: BSD-3-Clause
2-
/* Copyright 2019, Intel Corporation */
2+
/* Copyright 2019-2021, Intel Corporation */
33

44
/**
55
* Helper classes that represent C++ concepts
@@ -357,7 +357,7 @@ struct CompoundType {
357357
}
358358

359359
bool
360-
operator==(const CompoundType &rhs)
360+
operator==(const CompoundType &rhs) const
361361
{
362362
return counter == rhs.counter;
363363
}

tests/external/CMakeLists.txt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,22 @@ if (TEST_ARRAY)
101101
build_test(array_swap_2 libcxx/array/array.swap/swap.pass.cpp)
102102
add_test_generic(NAME array_swap_2 TRACERS none)
103103

104-
build_test(array_get_const_rv libcxx/array/array.tuple/get_const_rv.pass.cpp)
105-
add_test_generic(NAME array_get_const_rv TRACERS none)
106-
107104
build_test(array_get_const libcxx/array/array.tuple/get_const.pass.cpp)
108105
add_test_generic(NAME array_get_const TRACERS none)
109106

110-
build_test(array_get_rv libcxx/array/array.tuple/get_rv.pass.cpp)
111-
add_test_generic(NAME array_get_rv TRACERS none)
107+
if(CXX_STANDARD LESS 20)
108+
build_test(array_get_const_rv libcxx/array/array.tuple/get_const_rv.pass.cpp)
109+
add_test_generic(NAME array_get_const_rv TRACERS none)
110+
111+
build_test(array_get_rv libcxx/array/array.tuple/get_rv.pass.cpp)
112+
add_test_generic(NAME array_get_rv TRACERS none)
112113

113-
build_test(array_get libcxx/array/array.tuple/get.pass.cpp)
114-
add_test_generic(NAME array_get TRACERS none)
114+
build_test(array_get libcxx/array/array.tuple/get.pass.cpp)
115+
add_test_generic(NAME array_get TRACERS none)
116+
117+
build_test(array_cons_implicit_copy_const libcxx/array/array.cons/implicit_copy_const.pass.cpp)
118+
add_test_generic(NAME array_cons_implicit_copy_const TRACERS none)
119+
endif()
115120

116121
add_test_expect_failure(array_get libcxx/array/array.tuple/get.fail.cpp)
117122

tests/external/libcxx/array/array.cons/implicit_copy.pass.cpp

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,6 @@ struct Testcase1 {
4747
};
4848

4949
struct Testcase2 {
50-
typedef double T;
51-
typedef pmem::obj::array<const T, 3> C;
52-
C c = {{1.1, 2.2, 3.3}};
53-
C c2 = c;
54-
55-
void
56-
run()
57-
{
58-
((void)c2);
59-
static_assert(std::is_copy_constructible<C>::value, "");
60-
}
61-
};
62-
63-
struct Testcase3 {
6450
typedef double T;
6551
typedef pmem::obj::array<T, 0> C;
6652
C c = {{}};
@@ -74,23 +60,7 @@ struct Testcase3 {
7460
}
7561
};
7662

77-
struct Testcase4 {
78-
// const arrays of size 0 should disable the implicit copy
79-
// assignment operator.
80-
typedef double T;
81-
typedef pmem::obj::array<const T, 0> C;
82-
C c = {{}};
83-
C c2 = c;
84-
85-
void
86-
run()
87-
{
88-
((void)c2);
89-
static_assert(std::is_copy_constructible<C>::value, "");
90-
}
91-
};
92-
93-
struct Testcase5 {
63+
struct Testcase3 {
9464
typedef NoDefault T;
9565
typedef pmem::obj::array<T, 0> C;
9666
C c = {{}};
@@ -105,26 +75,10 @@ struct Testcase5 {
10575
}
10676
};
10777

108-
struct Testcase6 {
109-
typedef NoDefault T;
110-
typedef pmem::obj::array<const T, 0> C;
111-
C c = {{}};
112-
C c2 = c;
113-
void
114-
run()
115-
{
116-
((void)c2);
117-
static_assert(std::is_copy_constructible<C>::value, "");
118-
}
119-
};
120-
12178
struct root {
12279
pmem::obj::persistent_ptr<Testcase1> r1;
12380
pmem::obj::persistent_ptr<Testcase2> r2;
12481
pmem::obj::persistent_ptr<Testcase3> r3;
125-
pmem::obj::persistent_ptr<Testcase4> r4;
126-
pmem::obj::persistent_ptr<Testcase5> r5;
127-
pmem::obj::persistent_ptr<Testcase6> r6;
12882
};
12983

13084
void
@@ -138,20 +92,11 @@ run(pmem::obj::pool<root> &pop)
13892
pmem::obj::make_persistent<Testcase2>();
13993
pop.root()->r3 =
14094
pmem::obj::make_persistent<Testcase3>();
141-
pop.root()->r4 =
142-
pmem::obj::make_persistent<Testcase4>();
143-
pop.root()->r5 =
144-
pmem::obj::make_persistent<Testcase5>();
145-
pop.root()->r6 =
146-
pmem::obj::make_persistent<Testcase6>();
14795
});
14896

14997
pop.root()->r1->run();
15098
pop.root()->r2->run();
15199
pop.root()->r3->run();
152-
pop.root()->r4->run();
153-
pop.root()->r5->run();
154-
pop.root()->r6->run();
155100
} catch (...) {
156101
UT_ASSERT(0);
157102
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// Copyright 2018-2021, Intel Corporation
11+
//
12+
// Modified to test pmem::obj containers
13+
//
14+
15+
#include "unittest.hpp"
16+
17+
#include <libpmemobj++/container/array.hpp>
18+
#include <libpmemobj++/make_persistent.hpp>
19+
#include <libpmemobj++/persistent_ptr.hpp>
20+
#include <libpmemobj++/pool.hpp>
21+
#include <libpmemobj++/transaction.hpp>
22+
23+
struct NoDefault {
24+
NoDefault(int)
25+
{
26+
}
27+
};
28+
29+
struct Testcase1 {
30+
typedef double T;
31+
typedef pmem::obj::array<const T, 3> C;
32+
C c = {{1.1, 2.2, 3.3}};
33+
C c2 = c;
34+
35+
void
36+
run()
37+
{
38+
(void)c2;
39+
static_assert(std::is_copy_constructible<C>::value, "");
40+
}
41+
};
42+
43+
struct Testcase2 {
44+
// const arrays of size 0 should disable the implicit copy
45+
// assignment operator.
46+
typedef double T;
47+
typedef pmem::obj::array<const T, 0> C;
48+
C c = {{}};
49+
C c2 = c;
50+
51+
void
52+
run()
53+
{
54+
(void)c2;
55+
static_assert(std::is_copy_constructible<C>::value, "");
56+
}
57+
};
58+
59+
struct Testcase3 {
60+
typedef NoDefault T;
61+
typedef pmem::obj::array<const T, 0> C;
62+
C c = {{}};
63+
C c2 = c;
64+
void
65+
run()
66+
{
67+
(void)c2;
68+
static_assert(std::is_copy_constructible<C>::value, "");
69+
}
70+
};
71+
72+
struct root {
73+
pmem::obj::persistent_ptr<Testcase1> r1;
74+
pmem::obj::persistent_ptr<Testcase2> r2;
75+
pmem::obj::persistent_ptr<Testcase3> r3;
76+
};
77+
78+
void
79+
run(pmem::obj::pool<root> &pop)
80+
{
81+
try {
82+
pmem::obj::transaction::run(pop, [&] {
83+
pop.root()->r1 =
84+
pmem::obj::make_persistent<Testcase1>();
85+
pop.root()->r2 =
86+
pmem::obj::make_persistent<Testcase2>();
87+
pop.root()->r3 =
88+
pmem::obj::make_persistent<Testcase3>();
89+
});
90+
91+
pop.root()->r1->run();
92+
pop.root()->r2->run();
93+
pop.root()->r3->run();
94+
} catch (...) {
95+
UT_ASSERT(0);
96+
}
97+
}
98+
99+
static void
100+
test(int argc, char *argv[])
101+
{
102+
if (argc != 2)
103+
UT_FATAL("usage: %s file-name", argv[0]);
104+
105+
const char *path = argv[1];
106+
107+
pmem::obj::pool<root> pop;
108+
try {
109+
pop = pmem::obj::pool<root>::create(path, "implicit_copy.pass",
110+
PMEMOBJ_MIN_POOL,
111+
S_IWUSR | S_IRUSR);
112+
} catch (...) {
113+
UT_FATAL("!pmemobj_create: %s", path);
114+
}
115+
116+
run(pop);
117+
118+
pop.close();
119+
}
120+
121+
int
122+
main(int argc, char *argv[])
123+
{
124+
return run_test([&] { test(argc, argv); });
125+
}

tests/external/libcxx/array/array.cons/initializer_list.pass.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,13 @@ struct Testcase2 {
5050
struct Testcase3 {
5151
typedef double T;
5252
typedef pmem::obj::array<T, 3> C;
53+
#if __cplusplus > 201703L
54+
C c = {1};
55+
#else
56+
/* This syntax causes warning: braces around scalar initializer
57+
* on C++20*/
5358
C c = {{1}};
54-
59+
#endif
5560
void
5661
run()
5762
{

utils/docker/build.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ if [[ -z "${COMMAND}" ]]; then
5858
;;
5959
release)
6060
builds=(tests_gcc_release_cpp17_no_valgrind
61-
tests_clang_release_cpp11_no_valgrind)
61+
tests_clang_release_cpp11_no_valgrind
62+
tests_clang_release_cpp20_no_valgrind)
6263
COMMAND="./run-build.sh ${builds[@]}";
6364
;;
6465
valgrind)

utils/docker/prepare-for-build.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,12 @@ if [ "${CI_RUN}" == "YES" ]; then
9090
sudo_password chmod 0777 ${TEST_DIR}
9191
sudo_password mount -o size=2G -t tmpfs none ${TEST_DIR}
9292
fi || true
93+
94+
echo "CMake version:"
95+
cmake --version
96+
97+
# assign CMake's version to variable(s) - a single number representation for easier comparison
98+
CMAKE_VERSION=$(cmake --version | head -n1 | grep -P -o "\d+\.\d+")
99+
CMAKE_VERSION_MAJOR=$(echo ${CMAKE_VERSION} | cut -d. -f1)
100+
CMAKE_VERSION_MINOR=$(echo ${CMAKE_VERSION} | cut -d. -f2)
101+
CMAKE_VERSION_NUMBER=${CMAKE_VERSION_MAJOR}${CMAKE_VERSION_MINOR}

0 commit comments

Comments
 (0)