Skip to content

Commit 5590637

Browse files
authored
[orc-rt] Add const support to move_only_function. (#157781)
Adds support for both const move_only_functions, and const callees.
1 parent cc05266 commit 5590637

File tree

2 files changed

+117
-4
lines changed

2 files changed

+117
-4
lines changed

orc-rt/include/orc-rt/move_only_function.h

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,71 @@ class GenericCallableImpl : public GenericCallable<RetT, ArgTs...> {
5050
CallableT Callable;
5151
};
5252

53+
template <typename RetT, typename... ArgTs> class GenericConstCallable {
54+
public:
55+
virtual ~GenericConstCallable() = default;
56+
virtual RetT call(ArgTs &&...Args) const = 0;
57+
};
58+
59+
template <typename CallableT, typename RetT, typename... ArgTs>
60+
class GenericConstCallableImpl : public GenericConstCallable<RetT, ArgTs...> {
61+
public:
62+
GenericConstCallableImpl(CallableT &&Callable)
63+
: Callable(std::move(Callable)) {}
64+
RetT call(ArgTs &&...Args) const override {
65+
return Callable(std::forward<ArgTs>(Args)...);
66+
}
67+
68+
private:
69+
CallableT Callable;
70+
};
71+
5372
} // namespace move_only_function_detail
5473

5574
template <typename FnT> class move_only_function;
5675

5776
template <typename RetT, typename... ArgTs>
5877
class move_only_function<RetT(ArgTs...)> {
78+
private:
79+
using GenericCallable =
80+
move_only_function_detail::GenericCallable<RetT, ArgTs...>;
81+
template <typename CallableT>
82+
using GenericCallableImpl =
83+
move_only_function_detail::GenericCallableImpl<CallableT, RetT, ArgTs...>;
84+
85+
public:
86+
move_only_function() = default;
87+
move_only_function(std::nullptr_t) {}
88+
move_only_function(move_only_function &&) = default;
89+
move_only_function(const move_only_function &) = delete;
90+
move_only_function &operator=(move_only_function &&) = default;
91+
move_only_function &operator=(const move_only_function &) = delete;
92+
93+
template <typename CallableT>
94+
move_only_function(CallableT &&Callable)
95+
: C(std::make_unique<GenericCallableImpl<std::decay_t<CallableT>>>(
96+
std::move(Callable))) {}
97+
98+
RetT operator()(ArgTs... Params) const {
99+
return C->call(std::forward<ArgTs>(Params)...);
100+
}
101+
102+
explicit operator bool() const { return !!C; }
103+
104+
private:
105+
std::unique_ptr<GenericCallable> C;
106+
};
107+
108+
template <typename RetT, typename... ArgTs>
109+
class move_only_function<RetT(ArgTs...) const> {
110+
private:
111+
using GenericCallable =
112+
move_only_function_detail::GenericConstCallable<RetT, ArgTs...>;
113+
template <typename CallableT>
114+
using GenericCallableImpl =
115+
move_only_function_detail::GenericConstCallableImpl<CallableT, RetT,
116+
ArgTs...>;
117+
59118
public:
60119
move_only_function() = default;
61120
move_only_function(std::nullptr_t) {}
@@ -66,17 +125,17 @@ class move_only_function<RetT(ArgTs...)> {
66125

67126
template <typename CallableT>
68127
move_only_function(CallableT &&Callable)
69-
: C(std::make_unique<move_only_function_detail::GenericCallableImpl<
70-
std::decay_t<CallableT>, RetT, ArgTs...>>(std::move(Callable))) {}
128+
: C(std::make_unique<const GenericCallableImpl<std::decay_t<CallableT>>>(
129+
std::move(Callable))) {}
71130

72-
RetT operator()(ArgTs... Params) {
131+
RetT operator()(ArgTs... Params) const {
73132
return C->call(std::forward<ArgTs>(Params)...);
74133
}
75134

76135
explicit operator bool() const { return !!C; }
77136

78137
private:
79-
std::unique_ptr<move_only_function_detail::GenericCallable<RetT, ArgTs...>> C;
138+
std::unique_ptr<const GenericCallable> C;
80139
};
81140

82141
} // namespace orc_rt

orc-rt/unittests/move_only_function-test.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,57 @@ TEST(MoveOnlyFunctionTest, BooleanConversion) {
174174
move_only_function<void()> F = []() {};
175175
EXPECT_TRUE(F);
176176
}
177+
178+
class ConstCallCounter {
179+
public:
180+
ConstCallCounter(size_t &NonConst, size_t &Const)
181+
: NonConst(NonConst), Const(Const) {}
182+
void operator()() { ++NonConst; }
183+
void operator()() const { ++Const; }
184+
185+
private:
186+
size_t &NonConst;
187+
size_t &Const;
188+
};
189+
190+
TEST(MoveOnlyFunctionTest, Constness) {
191+
{
192+
// Non-const move-only-function, non-const callable.
193+
size_t NonConst = 0;
194+
size_t Const = 0;
195+
move_only_function<void()> F(ConstCallCounter(NonConst, Const));
196+
F();
197+
EXPECT_EQ(NonConst, 1U);
198+
EXPECT_EQ(Const, 0U);
199+
}
200+
201+
{
202+
// const move-only-function, non-const callable.
203+
size_t NonConst = 0;
204+
size_t Const = 0;
205+
const move_only_function<void()> F(ConstCallCounter(NonConst, Const));
206+
F();
207+
EXPECT_EQ(NonConst, 1U);
208+
EXPECT_EQ(Const, 0U);
209+
}
210+
211+
{
212+
// Non-const move-only-function, const callable.
213+
size_t NonConst = 0;
214+
size_t Const = 0;
215+
move_only_function<void() const> F(ConstCallCounter(NonConst, Const));
216+
F();
217+
EXPECT_EQ(NonConst, 0U);
218+
EXPECT_EQ(Const, 1U);
219+
}
220+
221+
{
222+
// const move-only-function, const callable.
223+
size_t NonConst = 0;
224+
size_t Const = 0;
225+
const move_only_function<void() const> F(ConstCallCounter(NonConst, Const));
226+
F();
227+
EXPECT_EQ(NonConst, 0U);
228+
EXPECT_EQ(Const, 1U);
229+
}
230+
}

0 commit comments

Comments
 (0)