Skip to content

Commit 39a9c44

Browse files
committed
refactor(functional)
1 parent 36dea13 commit 39a9c44

File tree

6 files changed

+132
-71
lines changed

6 files changed

+132
-71
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
3+
#include "../macros.h"
4+
5+
#include <functional>
6+
7+
namespace stdsharp
8+
{
9+
inline constexpr struct bind_front_fn
10+
{
11+
[[nodiscard]] constexpr auto operator()(auto&&... args) const
12+
noexcept(noexcept(std::bind_front(cpp_forward(args)...))) //
13+
-> decltype(std::bind_front(cpp_forward(args)...))
14+
{
15+
return std::bind_front(cpp_forward(args)...);
16+
}
17+
} bind_front{};
18+
19+
#if __cpp_lib_bind_back >= 202202L
20+
inline constexpr struct bind_back_fn
21+
{
22+
[[nodiscard]] constexpr auto operator()(auto&&... args) const
23+
noexcept(noexcept(std::bind_back(cpp_forward(args)...))) //
24+
-> decltype(std::bind_back(cpp_forward(args)...))
25+
{
26+
return std::bind_back(cpp_forward(args)...);
27+
}
28+
} bind_back{};
29+
#endif
30+
}

include/stdsharp/functional/bind_lvalue.h

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#pragma once
2+
3+
#include "invoke.h"
4+
#include "project_invoke.h"
5+
#include "sequenced_invocables.h"
6+
7+
namespace stdsharp::details
8+
{
9+
template<typename Func, typename... BindArgs>
10+
struct perfect_bind_front
11+
{
12+
private:
13+
using indexed_values = indexed_values<std::conditional_t<
14+
lvalue_ref<BindArgs>,
15+
std::reference_wrapper<std::remove_reference_t<BindArgs>>,
16+
std::remove_cvref_t<BindArgs>>...>;
17+
18+
template<std::size_t I, typename Self>
19+
constexpr decltype(auto) unref(this Self&& self) noexcept
20+
{
21+
auto&& bind_args = forward_cast<Self, perfect_bind_front>(self).bind_args;
22+
if constexpr(lvalue_ref<type_at<I, BindArgs...>>) return cpp_forward(bind_args).get();
23+
else return cpp_forward(bind_args);
24+
}
25+
26+
template<std::size_t I, typename Self>
27+
using unref_t = decltype(std::declval<Self>().template unref<I>());
28+
29+
public:
30+
Func func;
31+
indexed_values bind_args;
32+
33+
private:
34+
template<typename Self, typename... Args, std::size_t... I>
35+
requires std::invocable<forward_cast_t<Self, Func>, unref_t<I, Self>..., Args...>
36+
constexpr decltype(auto) impl(
37+
this Self&& self,
38+
Args&&... args,
39+
const std::index_sequence<I...> /*unused*/
40+
) noexcept(nothrow_invocable<forward_cast_t<Self, Func>, unref_t<I, Self>..., Args...>)
41+
{
42+
auto&& this_ = forward_cast<Self, perfect_bind_front>(self);
43+
return invoke(
44+
cpp_forward(this_).func,
45+
cpp_forward(this_).template unref<I>()...,
46+
cpp_forward(args)...
47+
);
48+
}
49+
50+
public:
51+
template<typename Self, typename... Args>
52+
constexpr decltype(auto) operator()(Self&& self, Args&&... args) noexcept( //
53+
noexcept( //
54+
forward_cast<Self, perfect_bind_front>(self)
55+
.impl(cpp_forward(args)..., std::index_sequence_for<BindArgs...>{})
56+
)
57+
)
58+
requires requires {
59+
forward_cast<Self, perfect_bind_front>(self).impl(
60+
cpp_forward(args)...,
61+
std::index_sequence_for<BindArgs...>{}
62+
);
63+
}
64+
{
65+
return forward_cast<Self, perfect_bind_front>(self).impl(
66+
cpp_forward(args)...,
67+
std::index_sequence_for<BindArgs...>{}
68+
);
69+
}
70+
};
71+
}
72+
73+
namespace stdsharp
74+
{
75+
template<typename... Args>
76+
struct deduction<details::perfect_bind_front, Args...>
77+
{
78+
using type = details::perfect_bind_front<Args...>;
79+
};
80+
81+
using perfect_bind_front_fn = make_template_type_fn<details::perfect_bind_front>;
82+
83+
inline constexpr perfect_bind_front_fn perfect_bind_front{};
84+
}

include/stdsharp/functional/project_invoke.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace stdsharp
88
{
9-
inline constexpr struct projected_invoke_fn
9+
inline constexpr struct project_invoke_fn
1010
{
1111
template<typename Fn, typename Projector, typename... Args>
1212
requires requires {
@@ -24,8 +24,8 @@ namespace stdsharp
2424
} project_invoke{};
2525

2626
template<typename... Args>
27-
concept project_invocable = std::invocable<projected_invoke_fn, Args...>;
27+
concept project_invocable = std::invocable<project_invoke_fn, Args...>;
2828

2929
template<typename... Args>
30-
concept project_nothrow_invocable = nothrow_invocable<projected_invoke_fn, Args...>;
30+
concept project_nothrow_invocable = nothrow_invocable<project_invoke_fn, Args...>;
3131
}

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ set(src
1616
# src/containers/actions.cpp
1717
# src/containers/concepts.cpp
1818
# src/filesystem/filesystem.cpp
19+
src/functional/perfect_bind_front.cpp
1920
# src/functional/pipeable.cpp
2021
src/functional/sequenced_invocables.cpp
2122
# src/functional/symmetric_operations.cpp
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "stdsharp/functional/perfect_bind_front.h"
2+
#include "stdsharp/type_traits/object.h"
3+
#include "test.h"
4+
5+
using namespace stdsharp;
6+
using namespace std;
7+
8+
SCENARIO("perfect bind front", "[functional]")
9+
{
10+
const struct : unique_object
11+
{
12+
int value;
13+
} obj{.value = 42};
14+
}

0 commit comments

Comments
 (0)