Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ target_sources(
include/stdx/utility.hpp)

if(PROJECT_IS_TOP_LEVEL)
include(CTest)
add_docs(docs)
add_subdirectory(test)
clang_tidy_interface(stdx)
Expand Down
27 changes: 19 additions & 8 deletions docs/functional.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ NOTE: https://wg21.link/P2714[P2714] added the ability (in C\\++26) to use a
non-type template parameter for the bound function; this works for function
pointers in C++17, and also for lambda expressions in C++20 and beyond.

=== `dereference`

`dereference` is a function object like
https://en.cppreference.com/w/cpp/utility/functional/negate.html[`std::negate`],
except it calls (unary) `operator*` instead of `operator-`.

It also has a specialization for `void` which is _transparent_ like that of
https://en.cppreference.com/w/cpp/utility/functional/negate_void.html[`std::negate`].

=== `safe_identity`

`safe_identity` is a function object (of type `safe_identity_t`) similar
Expand All @@ -34,6 +43,16 @@ NOTE: In standard usage, the type is `std::identity` and we must instantiate it
to use it; in `stdx`, the type is `safe_identity_t` and `safe_identity` is a
`constexpr inline` variable of that type.

=== `unary_plus`

`unary_plus` is a function object like
https://en.cppreference.com/w/cpp/utility/functional/negate.html[`std::negate`],
except it calls (unary) `operator+` instead of `operator-`.

It also has a specialization for `void` which is _transparent_ like that of
https://en.cppreference.com/w/cpp/utility/functional/negate_void.html[`std::negate`].
>>>>>>> 7a78082 (:sparkles: Add `dereference`)

=== `with_result_of`

`with_result_of` is a class that can be used for lazy evaluation.
Expand All @@ -59,11 +78,3 @@ v.emplace(0, stdx::with_result_of{make_S}); // this constructs S in-place thanks
`with_result_of` can help to achieve in-place construction, effectively by deferring
evaluation of function arguments.

=== `unary_plus`

`unary_plus` is a function object like
https://en.cppreference.com/w/cpp/utility/functional/negate.html[`std::negate`],
except it calls (unary) `operator+` instead of `operator-`.

It also has a specialization for `void` which is _transparent_ like that of
https://en.cppreference.com/w/cpp/utility/functional/negate_void.html[`std::negate`].
28 changes: 26 additions & 2 deletions include/stdx/functional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,15 @@ template <auto F, typename... Args> constexpr auto bind_back(Args &&...args) {

#endif

// NOLINTBEGIN(modernize-use-constraints)
template <typename T = void> struct unary_plus {
constexpr auto operator()(T const &arg) const -> decltype(+arg) {
return +arg;
template <typename U,
typename = std::enable_if_t<is_same_unqualified_v<U, T>>>
constexpr auto operator()(U &&u) const -> decltype(+std::forward<U>(u)) {
return +std::forward<U>(u);
}
};
// NOLINTEND(modernize-use-constraints)

template <> struct unary_plus<void> {
using is_transparent = int;
Expand All @@ -195,5 +199,25 @@ constexpr inline struct safe_identity_t {
return T(std::forward<T>(t));
}
} safe_identity;

// NOLINTBEGIN(modernize-use-constraints)
template <typename T = void> struct dereference {
template <typename U,
typename = std::enable_if_t<is_same_unqualified_v<U, T>>>
constexpr auto operator()(U &&u) const -> decltype(*std::forward<U>(u)) {
return *std::forward<U>(u);
}
};
// NOLINTEND(modernize-use-constraints)

template <> struct dereference<void> {
using is_transparent = int;

template <typename T>
constexpr auto operator()(T &&arg) const
-> decltype(*std::forward<T>(arg)) {
return *std::forward<T>(arg);
}
};
} // namespace v1
} // namespace stdx
16 changes: 16 additions & 0 deletions test/functional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ constexpr auto

struct S {};
constexpr auto operator+(S) { return 17; }
constexpr auto operator*(S) { return 28; }
} // namespace

TEST_CASE("unary_plus", "[functional]") {
Expand Down Expand Up @@ -89,3 +90,18 @@ TEST_CASE("safe_identity cvref categories", "[functional]") {
declval<int const volatile &&>())),
int>);
}

TEST_CASE("dereference", "[functional]") {
int x{28};
CHECK(stdx::dereference<int *>{}(&x) == 28);
CHECK(stdx::dereference<>{}(&x) == 28);
}

TEST_CASE("dereference transparency", "[functional]") {
STATIC_REQUIRE(not detect_is_transparent<stdx::dereference<int *>>);
STATIC_REQUIRE(detect_is_transparent<stdx::dereference<>>);
}

TEST_CASE("dereference calls operator*", "[functional]") {
STATIC_REQUIRE(stdx::dereference<>{}(S{}) == 28);
}
Loading