[libcxx-commits] [PATCH] D110994: [libc++] Make test_allocator constexpr-friendly for constexpr string/vector
Arthur O'Dwyer via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Oct 2 17:20:13 PDT 2021
Quuxplusone requested changes to this revision.
Quuxplusone added a comment.
This revision now requires changes to proceed.
I don't believe this gets us all the way to constexpr-friendliness yet; see my comments and please let me know if anything I said fails to make sense. :)
================
Comment at: libcxx/test/support/test_allocator.h:69
+ test_allocator_statistics* stats_;
+};
----------------
You've correctly intuited about half of the fix I intended. :) So this is a step in the right direction, but you need to take one more step before it'll fix the constexprness problem.
The next step is to get rid of the global `::alloc_stats`. Instead, each caller is going to do something like (e.g. in `move_alloc.pass.cpp`)
```
test_allocator_statistics alloc_stats; // LOCAL VARIABLE
{
typedef test_allocator<char> A;
typedef std::basic_string<char, std::char_traits<char>, A> S;
#if TEST_STD_VER > 14
static_assert((noexcept(S{})), "" );
#elif TEST_STD_VER >= 11
static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "");
#endif
S s1("Twas brillig, and the slivy toves did gyre and gymbal in the wabe");
S s2(std::move(s1), A(1, &alloc_stats)); // DIFFERENCE HERE
}
assert(alloc_stats.alloc_count == alloc_count);
```
And //then// this test will be trivially constexpr-ible, because it won't depend on any global runtime state.
I'm assuming that as part of this transformation, the `test_alloc_base` class will actually go away, because now it doesn't really serve any purpose. But maybe I'm missing something.
================
Comment at: libcxx/test/support/test_allocator.h:90
- test_allocator() TEST_NOEXCEPT : data_(0), id_(0) {++count;}
- explicit test_allocator(int i, int id = 0) TEST_NOEXCEPT : data_(i), id_(id)
- {++count;}
- test_allocator(const test_allocator& a) TEST_NOEXCEPT : data_(a.data_),
+ TEST_CONSTEXPR_CXX14 test_allocator(test_allocator_statistics* stats = &alloc_stats) TEST_NOEXCEPT
+ : test_alloc_base(stats), data_(0), id_(0)
----------------
This ctor overload set will become more like
```
test_allocator_statistics *stats_ = nullptr;
int data_ = 0; // participates in equality
int id_ = 0; // unique identifier, doesn't participate in equality
~~~
explicit test_allocator() = default;
TEST_CONSTEXPR explicit test_allocator(int data) TEST_NOEXCEPT :
data_(data) {}
TEST_CONSTEXPR explicit test_allocator(int data, int id) TEST_NOEXCEPT :
data_(data), id_(id) {}
TEST_CONSTEXPR_CXX14 explicit test_allocator(int data, test_allocator_statistics *stats) TEST_NOEXCEPT :
stats_(stats), data_(data) { stats_->count += 1; }
TEST_CONSTEXPR_CXX14 test_allocator(const test_allocator& a) TEST_NOEXCEPT :
stats_(a.stats), data_(a.data), id_(a.id_)
{
if (stats_ != nullptr) {
stats_->count += 1;
stats_->copied += 1;
}
assert(a.data_ != destructed_value && a.id_ != destructed_value && "copying from destroyed allocator");
}
```
and so on. (Notice that it's OK to use NSDMIs and `=default` in C++03 mode, because Clang supports them as extensions, and we don't claim to support any non-Clang compilers prior to C++11 mode.)
Also notice that I'm drive-by applying my general guidelines of "one signature, one declaration" — default arguments are the devil — and "mark all ctors `explicit` except for copy and move ctors"; and applying my specific aforementioned guideline of "use the most aggressive constexpr macros possible, in test/support code."
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D110994/new/
https://reviews.llvm.org/D110994
More information about the libcxx-commits
mailing list