Skip to content

Commit 765bdb8

Browse files
Added invocable affordance
1 parent f15c86c commit 765bdb8

3 files changed

Lines changed: 153 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ int main() {
6565
- `destructible`
6666
- `movable`
6767
- `copyable`
68+
- `invocable<Fn>`
6869
- `extractable<In>`
6970
- `insertable<Out>`
7071
- `allocator_storage<Allocator>`
@@ -78,7 +79,6 @@ int main() {
7879
- `inplace_storage<Size, Align>`
7980
- `shared_storage`
8081
- `copy_on_write_storage`
81-
- `invocable` affordance template
8282
- `assignment` support for type erasing sinks
8383
- `slot_dispatch` for vtable lookup using a static slot map key
8484
- Affordances for iterators

include/simply/invocable.hpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#ifndef SIMPLY_INVOCABLE_HPP
2+
#define SIMPLY_INVOCABLE_HPP
3+
4+
#include <simply/iface.hpp>
5+
#include <simply/impl.hpp>
6+
7+
namespace simply {
8+
9+
template <typename Fn, typename R, typename... Args>
10+
concept invocable_with = requires {
11+
{ std::declval<Fn>()(std::declval<Args>()...) } -> std::same_as<R>;
12+
};
13+
14+
template <typename Fn, typename R, typename... Args>
15+
concept nothrow_invocable_with = requires {
16+
{ std::declval<Fn>()(std::declval<Args>()...) } noexcept -> std::same_as<R>;
17+
};
18+
19+
template <typename Fn>
20+
struct invocable {
21+
static_assert(std::is_function_v<Fn>);
22+
};
23+
24+
template <typename R, typename... Args, bool NoExcept>
25+
struct invocable<R(Args...) noexcept(NoExcept)>
26+
: simply::composes<simply::invocable<R(Args...) & noexcept(NoExcept)>,
27+
simply::invocable<R(Args...) && noexcept(NoExcept)>> {};
28+
29+
template <typename R, typename... Args, bool NoExcept>
30+
struct invocable<R(Args...) const noexcept(NoExcept)>
31+
: simply::composes<
32+
simply::invocable<R(Args...) const & noexcept(NoExcept)>,
33+
simply::invocable<R(Args...) const && noexcept(NoExcept)>> {};
34+
35+
template <typename R, typename... Args>
36+
struct invocable<R(Args...) &> : simply::member_base {
37+
template <typename Fn>
38+
requires simply::invocable_with<Fn &, R, Args...>
39+
static constexpr auto fn(std::type_identity_t<Fn> &self, Args... args) -> R {
40+
return self(std::forward<Args>(args)...);
41+
}
42+
};
43+
44+
template <typename R, typename... Args>
45+
struct invocable<R(Args...) &&> : simply::member_base {
46+
template <typename Fn>
47+
requires simply::invocable_with<Fn, R, Args...>
48+
static constexpr auto fn(std::type_identity_t<Fn> &&self, Args... args) -> R {
49+
return std::move(self)(std::forward<Args>(args)...);
50+
}
51+
};
52+
53+
template <typename R, typename... Args>
54+
struct invocable<R(Args...) const &> : simply::member_base {
55+
template <typename Fn>
56+
requires simply::invocable_with<const Fn &, R, Args...>
57+
static constexpr auto fn(const std::type_identity_t<Fn> &self, Args... args)
58+
-> R {
59+
return self(std::forward<Args>(args)...);
60+
}
61+
};
62+
63+
template <typename R, typename... Args>
64+
struct invocable<R(Args...) const &&> : simply::member_base {
65+
template <typename Fn>
66+
requires simply::invocable_with<const Fn, R, Args...>
67+
static constexpr auto fn(const std::type_identity_t<Fn> &&self, Args... args)
68+
-> R {
69+
return std::move(self)(std::forward<Args>(args)...);
70+
}
71+
};
72+
73+
template <typename R, typename... Args>
74+
struct invocable<R(Args...) & noexcept> : simply::member_base {
75+
template <typename Fn>
76+
requires simply::nothrow_invocable_with<Fn &, R, Args...>
77+
static constexpr auto fn(std::type_identity_t<Fn> &self,
78+
Args... args) noexcept -> R {
79+
return self(std::forward<Args>(args)...);
80+
}
81+
};
82+
83+
template <typename R, typename... Args>
84+
struct invocable<R(Args...) && noexcept> : simply::member_base {
85+
template <typename Fn>
86+
requires simply::nothrow_invocable_with<Fn, R, Args...>
87+
static constexpr auto fn(std::type_identity_t<Fn> &&self,
88+
Args... args) noexcept -> R {
89+
return std::move(self)(std::forward<Args>(args)...);
90+
}
91+
};
92+
93+
template <typename R, typename... Args>
94+
struct invocable<R(Args...) const & noexcept> : simply::member_base {
95+
template <typename Fn>
96+
requires simply::nothrow_invocable_with<const Fn &, R, Args...>
97+
static constexpr auto fn(const std::type_identity_t<Fn> &self,
98+
Args... args) noexcept -> R {
99+
return self(std::forward<Args>(args)...);
100+
}
101+
};
102+
103+
template <typename R, typename... Args>
104+
struct invocable<R(Args...) const && noexcept> : simply::member_base {
105+
template <typename Fn>
106+
requires simply::nothrow_invocable_with<const Fn, R, Args...>
107+
static constexpr auto fn(const std::type_identity_t<Fn> &&self,
108+
Args... args) noexcept -> R {
109+
return std::move(self)(std::forward<Args>(args)...);
110+
}
111+
};
112+
113+
template <typename R, typename... Args, bool NoExcept, typename Self>
114+
struct iface<simply::invocable<R(Args...) & noexcept(NoExcept)>, Self> {
115+
constexpr auto operator()(this Self &self, Args... args) noexcept(NoExcept)
116+
-> R {
117+
return simply::fn<simply::invocable<R(Args...) & noexcept(NoExcept)>, Self>(
118+
self, std::forward<Args>(args)...);
119+
}
120+
};
121+
122+
template <typename R, typename... Args, bool NoExcept, typename Self>
123+
struct iface<simply::invocable<R(Args...) && noexcept(NoExcept)>, Self> {
124+
constexpr auto operator()(this Self &&self, Args... args) noexcept(NoExcept)
125+
-> R {
126+
return simply::fn<simply::invocable<R(Args...) && noexcept(NoExcept)>,
127+
Self>(std::move(self), std::forward<Args>(args)...);
128+
}
129+
};
130+
131+
template <typename R, typename... Args, bool NoExcept, typename Self>
132+
struct iface<simply::invocable<R(Args...) const & noexcept(NoExcept)>, Self> {
133+
constexpr auto operator()(this const Self &self,
134+
Args... args) noexcept(NoExcept) -> R {
135+
return simply::fn<simply::invocable<R(Args...) const & noexcept(NoExcept)>,
136+
Self>(self, std::forward<Args>(args)...);
137+
}
138+
};
139+
140+
template <typename R, typename... Args, bool NoExcept, typename Self>
141+
struct iface<simply::invocable<R(Args...) const && noexcept(NoExcept)>, Self> {
142+
constexpr auto operator()(this const Self &&self,
143+
Args... args) noexcept(NoExcept) -> R {
144+
return simply::fn<simply::invocable<R(Args...) const && noexcept(NoExcept)>,
145+
Self>(std::move(self), std::forward<Args>(args)...);
146+
}
147+
};
148+
149+
} // namespace simply
150+
151+
#endif // SIMPLY_INVOCABLE_HPP

include/simply/simply.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <simply/iface.hpp>
1414
#include <simply/impl.hpp>
1515
#include <simply/insertable.hpp>
16+
#include <simply/invocable.hpp>
1617
#include <simply/movable.hpp>
1718
#include <simply/scope.hpp>
1819
#include <simply/storage.hpp>

0 commit comments

Comments
 (0)