[orc-rt] Add const support to move_only_function. (#157781)
Adds support for both const move_only_functions, and const callees.
This commit is contained in:
parent
cc052667b4
commit
55906374f8
@ -50,12 +50,38 @@ private:
|
||||
CallableT Callable;
|
||||
};
|
||||
|
||||
template <typename RetT, typename... ArgTs> class GenericConstCallable {
|
||||
public:
|
||||
virtual ~GenericConstCallable() = default;
|
||||
virtual RetT call(ArgTs &&...Args) const = 0;
|
||||
};
|
||||
|
||||
template <typename CallableT, typename RetT, typename... ArgTs>
|
||||
class GenericConstCallableImpl : public GenericConstCallable<RetT, ArgTs...> {
|
||||
public:
|
||||
GenericConstCallableImpl(CallableT &&Callable)
|
||||
: Callable(std::move(Callable)) {}
|
||||
RetT call(ArgTs &&...Args) const override {
|
||||
return Callable(std::forward<ArgTs>(Args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
CallableT Callable;
|
||||
};
|
||||
|
||||
} // namespace move_only_function_detail
|
||||
|
||||
template <typename FnT> class move_only_function;
|
||||
|
||||
template <typename RetT, typename... ArgTs>
|
||||
class move_only_function<RetT(ArgTs...)> {
|
||||
private:
|
||||
using GenericCallable =
|
||||
move_only_function_detail::GenericCallable<RetT, ArgTs...>;
|
||||
template <typename CallableT>
|
||||
using GenericCallableImpl =
|
||||
move_only_function_detail::GenericCallableImpl<CallableT, RetT, ArgTs...>;
|
||||
|
||||
public:
|
||||
move_only_function() = default;
|
||||
move_only_function(std::nullptr_t) {}
|
||||
@ -66,17 +92,50 @@ public:
|
||||
|
||||
template <typename CallableT>
|
||||
move_only_function(CallableT &&Callable)
|
||||
: C(std::make_unique<move_only_function_detail::GenericCallableImpl<
|
||||
std::decay_t<CallableT>, RetT, ArgTs...>>(std::move(Callable))) {}
|
||||
: C(std::make_unique<GenericCallableImpl<std::decay_t<CallableT>>>(
|
||||
std::move(Callable))) {}
|
||||
|
||||
RetT operator()(ArgTs... Params) {
|
||||
RetT operator()(ArgTs... Params) const {
|
||||
return C->call(std::forward<ArgTs>(Params)...);
|
||||
}
|
||||
|
||||
explicit operator bool() const { return !!C; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<move_only_function_detail::GenericCallable<RetT, ArgTs...>> C;
|
||||
std::unique_ptr<GenericCallable> C;
|
||||
};
|
||||
|
||||
template <typename RetT, typename... ArgTs>
|
||||
class move_only_function<RetT(ArgTs...) const> {
|
||||
private:
|
||||
using GenericCallable =
|
||||
move_only_function_detail::GenericConstCallable<RetT, ArgTs...>;
|
||||
template <typename CallableT>
|
||||
using GenericCallableImpl =
|
||||
move_only_function_detail::GenericConstCallableImpl<CallableT, RetT,
|
||||
ArgTs...>;
|
||||
|
||||
public:
|
||||
move_only_function() = default;
|
||||
move_only_function(std::nullptr_t) {}
|
||||
move_only_function(move_only_function &&) = default;
|
||||
move_only_function(const move_only_function &) = delete;
|
||||
move_only_function &operator=(move_only_function &&) = default;
|
||||
move_only_function &operator=(const move_only_function &) = delete;
|
||||
|
||||
template <typename CallableT>
|
||||
move_only_function(CallableT &&Callable)
|
||||
: C(std::make_unique<const GenericCallableImpl<std::decay_t<CallableT>>>(
|
||||
std::move(Callable))) {}
|
||||
|
||||
RetT operator()(ArgTs... Params) const {
|
||||
return C->call(std::forward<ArgTs>(Params)...);
|
||||
}
|
||||
|
||||
explicit operator bool() const { return !!C; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<const GenericCallable> C;
|
||||
};
|
||||
|
||||
} // namespace orc_rt
|
||||
|
||||
@ -174,3 +174,57 @@ TEST(MoveOnlyFunctionTest, BooleanConversion) {
|
||||
move_only_function<void()> F = []() {};
|
||||
EXPECT_TRUE(F);
|
||||
}
|
||||
|
||||
class ConstCallCounter {
|
||||
public:
|
||||
ConstCallCounter(size_t &NonConst, size_t &Const)
|
||||
: NonConst(NonConst), Const(Const) {}
|
||||
void operator()() { ++NonConst; }
|
||||
void operator()() const { ++Const; }
|
||||
|
||||
private:
|
||||
size_t &NonConst;
|
||||
size_t &Const;
|
||||
};
|
||||
|
||||
TEST(MoveOnlyFunctionTest, Constness) {
|
||||
{
|
||||
// Non-const move-only-function, non-const callable.
|
||||
size_t NonConst = 0;
|
||||
size_t Const = 0;
|
||||
move_only_function<void()> F(ConstCallCounter(NonConst, Const));
|
||||
F();
|
||||
EXPECT_EQ(NonConst, 1U);
|
||||
EXPECT_EQ(Const, 0U);
|
||||
}
|
||||
|
||||
{
|
||||
// const move-only-function, non-const callable.
|
||||
size_t NonConst = 0;
|
||||
size_t Const = 0;
|
||||
const move_only_function<void()> F(ConstCallCounter(NonConst, Const));
|
||||
F();
|
||||
EXPECT_EQ(NonConst, 1U);
|
||||
EXPECT_EQ(Const, 0U);
|
||||
}
|
||||
|
||||
{
|
||||
// Non-const move-only-function, const callable.
|
||||
size_t NonConst = 0;
|
||||
size_t Const = 0;
|
||||
move_only_function<void() const> F(ConstCallCounter(NonConst, Const));
|
||||
F();
|
||||
EXPECT_EQ(NonConst, 0U);
|
||||
EXPECT_EQ(Const, 1U);
|
||||
}
|
||||
|
||||
{
|
||||
// const move-only-function, const callable.
|
||||
size_t NonConst = 0;
|
||||
size_t Const = 0;
|
||||
const move_only_function<void() const> F(ConstCallCounter(NonConst, Const));
|
||||
F();
|
||||
EXPECT_EQ(NonConst, 0U);
|
||||
EXPECT_EQ(Const, 1U);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user