Skip to content

Latest commit

 

History

History
80 lines (58 loc) · 3 KB

File metadata and controls

80 lines (58 loc) · 3 KB

functional.hpp

Note
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 std::negate, except it calls (unary) operator* instead of operator-.

It also has a specialization for void which is transparent like that of std::negate.

safe_identity

safe_identity is a function object (of type safe_identity_t) similar in intent to std::identity. A call to safe_identity returns its argument unchanged. However, the vital difference with safe_identity is in the value category of what is returned.

int x;
auto f() -> int;

decltype(auto) r1 = std::identity{}(x);       // r1 has type int &
decltype(auto) r2 = std::identity{}(f());     // r2 has type int && - dangling!

decltype(auto) r3 = stdx::safe_identity(x);   // r3 has type int &
decltype(auto) r4 = stdx::safe_identity(f()); // r4 has type int - no longer dangling
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 std::negate, except it calls (unary) operator+ instead of operator-.

It also has a specialization for void which is transparent like that of std::negate. >>>>>>> 7a78082 (:sparkles: Add dereference)

with_result_of

with_result_of is a class that can be used for lazy evaluation. with_result_of wraps a callable (often a lambda expression) and can implicitly convert to the return type of the callable. It may be passed to functions that perfectly forward their arguments - a good example is an emplace function on a container - and the conversion happens only when the required value is actually used.

// S is a type that is some work to construct
// so we use a maker function
struct S { ... };
auto make_S() -> S;

std::unordered_map<int, S> m;

v.emplace(0, make_S()); // this works, but incurs a temporary construct, move and destruct
v.emplace(0, stdx::with_result_of{make_S}); // this constructs S in-place thanks to RVO

with_result_of can help to achieve in-place construction, effectively by deferring evaluation of function arguments.