diff --git a/docs/functional.adoc b/docs/functional.adoc index c6e0a8f..db56581 100644 --- a/docs/functional.adoc +++ b/docs/functional.adoc @@ -34,3 +34,12 @@ 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`]. diff --git a/include/stdx/functional.hpp b/include/stdx/functional.hpp index 0af9055..5497af9 100644 --- a/include/stdx/functional.hpp +++ b/include/stdx/functional.hpp @@ -170,5 +170,22 @@ template constexpr auto bind_back(Args &&...args) { } #endif + +template struct unary_plus { + constexpr auto operator()(T const &arg) const -> decltype(+arg) { + return +arg; + } +}; + +template <> struct unary_plus { + using is_transparent = int; + + template + constexpr auto operator()(T &&arg) const + -> decltype(+std::forward(arg)) { + return +std::forward(arg); + } +}; + } // namespace v1 } // namespace stdx diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1d888ca..bcfa47d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -43,6 +43,7 @@ add_tests( default_panic for_each_n_args function_traits + functional intrusive_forward_list intrusive_list intrusive_list_properties diff --git a/test/functional.cpp b/test/functional.cpp new file mode 100644 index 0000000..c013f3c --- /dev/null +++ b/test/functional.cpp @@ -0,0 +1,30 @@ +#include + +#include + +#include + +namespace { +template +constexpr auto detect_is_transparent = false; +template +constexpr auto + detect_is_transparent> = true; + +struct S {}; +constexpr auto operator+(S) { return 17; } +} // namespace + +TEST_CASE("unary_plus", "[functional]") { + STATIC_REQUIRE(stdx::unary_plus{}(17) == 17); + STATIC_REQUIRE(stdx::unary_plus<>{}(17) == 17); +} + +TEST_CASE("unary_plus transparency", "[functional]") { + STATIC_REQUIRE(not detect_is_transparent>); + STATIC_REQUIRE(detect_is_transparent>); +} + +TEST_CASE("unary_plus calls operator+", "[functional]") { + STATIC_REQUIRE(stdx::unary_plus<>{}(S{}) == 17); +}