Skip to content

Commit 30f589c

Browse files
author
Arthur O'Dwyer
committed
[libc++] Constexpr-proof some machinery in not_fn.pass.cpp. NFCI.
We don't need to use global variables here; we can store the "State" of this machinery on the stack, so that it's constexpr-friendly.
1 parent 4b33b23 commit 30f589c

File tree

1 file changed

+65
-63
lines changed

1 file changed

+65
-63
lines changed

libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp

Lines changed: 65 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -135,59 +135,60 @@ inline constexpr CallType operator|(CallType LHS, CallType RHS) {
135135
}
136136

137137
struct ForwardingCallObject {
138+
struct State {
139+
CallType last_call_type = CT_None;
140+
TypeID const& (*last_call_args)() = nullptr;
141+
142+
template <class ...Args>
143+
constexpr void set_call(CallType type) {
144+
assert(last_call_type == CT_None);
145+
assert(last_call_args == nullptr);
146+
last_call_type = type;
147+
last_call_args = &makeArgumentID<Args...>;
148+
}
149+
150+
template <class ...Args>
151+
constexpr bool check_call(CallType type) {
152+
bool result =
153+
last_call_type == type
154+
&& last_call_args
155+
&& *last_call_args == &makeArgumentID<Args...>;
156+
last_call_type = CT_None;
157+
last_call_args = nullptr;
158+
return result;
159+
}
160+
};
161+
162+
State *st_;
163+
164+
explicit constexpr ForwardingCallObject(State& st) : st_(&st) {}
138165

139166
template <class ...Args>
140-
bool operator()(Args&&...) & {
141-
set_call<Args&&...>(CT_NonConst | CT_LValue);
167+
constexpr bool operator()(Args&&...) & {
168+
st_->set_call<Args&&...>(CT_NonConst | CT_LValue);
142169
return true;
143170
}
144171

145172
template <class ...Args>
146-
bool operator()(Args&&...) const & {
147-
set_call<Args&&...>(CT_Const | CT_LValue);
173+
constexpr bool operator()(Args&&...) const & {
174+
st_->set_call<Args&&...>(CT_Const | CT_LValue);
148175
return true;
149176
}
150177

151178
// Don't allow the call operator to be invoked as an rvalue.
152179
template <class ...Args>
153-
bool operator()(Args&&...) && {
154-
set_call<Args&&...>(CT_NonConst | CT_RValue);
180+
constexpr bool operator()(Args&&...) && {
181+
st_->set_call<Args&&...>(CT_NonConst | CT_RValue);
155182
return true;
156183
}
157184

158185
template <class ...Args>
159-
bool operator()(Args&&...) const && {
160-
set_call<Args&&...>(CT_Const | CT_RValue);
186+
constexpr bool operator()(Args&&...) const && {
187+
st_->set_call<Args&&...>(CT_Const | CT_RValue);
161188
return true;
162189
}
163-
164-
template <class ...Args>
165-
static void set_call(CallType type) {
166-
assert(last_call_type == CT_None);
167-
assert(last_call_args == nullptr);
168-
last_call_type = type;
169-
last_call_args = &makeArgumentID<Args...>();
170-
}
171-
172-
template <class ...Args>
173-
static bool check_call(CallType type) {
174-
bool result =
175-
last_call_type == type
176-
&& last_call_args
177-
&& *last_call_args == makeArgumentID<Args...>();
178-
last_call_type = CT_None;
179-
last_call_args = nullptr;
180-
return result;
181-
}
182-
183-
static CallType last_call_type;
184-
static TypeID const* last_call_args;
185190
};
186191

187-
CallType ForwardingCallObject::last_call_type = CT_None;
188-
TypeID const* ForwardingCallObject::last_call_args = nullptr;
189-
190-
191192

192193
///////////////////////////////////////////////////////////////////////////////
193194
// BOOL TEST TYPES
@@ -467,85 +468,86 @@ void call_operator_sfinae_test() {
467468
void call_operator_forwarding_test()
468469
{
469470
using Fn = ForwardingCallObject;
470-
auto obj = std::not_fn(Fn{});
471+
Fn::State st;
472+
auto obj = std::not_fn(Fn{st});
471473
const auto& c_obj = obj;
472474
{ // test zero args
473475
obj();
474-
assert(Fn::check_call<>(CT_NonConst | CT_LValue));
476+
assert(st.check_call<>(CT_NonConst | CT_LValue));
475477
std::move(obj)();
476-
assert(Fn::check_call<>(CT_NonConst | CT_RValue));
478+
assert(st.check_call<>(CT_NonConst | CT_RValue));
477479
c_obj();
478-
assert(Fn::check_call<>(CT_Const | CT_LValue));
480+
assert(st.check_call<>(CT_Const | CT_LValue));
479481
std::move(c_obj)();
480-
assert(Fn::check_call<>(CT_Const | CT_RValue));
482+
assert(st.check_call<>(CT_Const | CT_RValue));
481483
}
482484
{ // test value categories
483485
int x = 42;
484486
const int cx = 42;
485487
obj(x);
486-
assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
488+
assert(st.check_call<int&>(CT_NonConst | CT_LValue));
487489
obj(cx);
488-
assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue));
490+
assert(st.check_call<const int&>(CT_NonConst | CT_LValue));
489491
obj(std::move(x));
490-
assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
492+
assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
491493
obj(std::move(cx));
492-
assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue));
494+
assert(st.check_call<const int&&>(CT_NonConst | CT_LValue));
493495
obj(42);
494-
assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
496+
assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
495497
}
496498
{ // test value categories - rvalue
497499
int x = 42;
498500
const int cx = 42;
499501
std::move(obj)(x);
500-
assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
502+
assert(st.check_call<int&>(CT_NonConst | CT_RValue));
501503
std::move(obj)(cx);
502-
assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue));
504+
assert(st.check_call<const int&>(CT_NonConst | CT_RValue));
503505
std::move(obj)(std::move(x));
504-
assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
506+
assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
505507
std::move(obj)(std::move(cx));
506-
assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue));
508+
assert(st.check_call<const int&&>(CT_NonConst | CT_RValue));
507509
std::move(obj)(42);
508-
assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
510+
assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
509511
}
510512
{ // test value categories - const call
511513
int x = 42;
512514
const int cx = 42;
513515
c_obj(x);
514-
assert(Fn::check_call<int&>(CT_Const | CT_LValue));
516+
assert(st.check_call<int&>(CT_Const | CT_LValue));
515517
c_obj(cx);
516-
assert(Fn::check_call<const int&>(CT_Const | CT_LValue));
518+
assert(st.check_call<const int&>(CT_Const | CT_LValue));
517519
c_obj(std::move(x));
518-
assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
520+
assert(st.check_call<int&&>(CT_Const | CT_LValue));
519521
c_obj(std::move(cx));
520-
assert(Fn::check_call<const int&&>(CT_Const | CT_LValue));
522+
assert(st.check_call<const int&&>(CT_Const | CT_LValue));
521523
c_obj(42);
522-
assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
524+
assert(st.check_call<int&&>(CT_Const | CT_LValue));
523525
}
524526
{ // test value categories - const call rvalue
525527
int x = 42;
526528
const int cx = 42;
527529
std::move(c_obj)(x);
528-
assert(Fn::check_call<int&>(CT_Const | CT_RValue));
530+
assert(st.check_call<int&>(CT_Const | CT_RValue));
529531
std::move(c_obj)(cx);
530-
assert(Fn::check_call<const int&>(CT_Const | CT_RValue));
532+
assert(st.check_call<const int&>(CT_Const | CT_RValue));
531533
std::move(c_obj)(std::move(x));
532-
assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
534+
assert(st.check_call<int&&>(CT_Const | CT_RValue));
533535
std::move(c_obj)(std::move(cx));
534-
assert(Fn::check_call<const int&&>(CT_Const | CT_RValue));
536+
assert(st.check_call<const int&&>(CT_Const | CT_RValue));
535537
std::move(c_obj)(42);
536-
assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
538+
assert(st.check_call<int&&>(CT_Const | CT_RValue));
537539
}
538540
{ // test multi arg
539541
const double y = 3.14;
540542
std::string s = "abc";
541543
obj(42, std::move(y), s, std::string{"foo"});
542-
Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue);
544+
assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue)));
543545
std::move(obj)(42, std::move(y), s, std::string{"foo"});
544-
Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue);
546+
assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue)));
545547
c_obj(42, std::move(y), s, std::string{"foo"});
546-
Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_LValue);
548+
assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_LValue)));
547549
std::move(c_obj)(42, std::move(y), s, std::string{"foo"});
548-
Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue);
550+
assert((st.check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue)));
549551
}
550552
}
551553

0 commit comments

Comments
 (0)