Reputation: 9369
Why should one prefer to call std::ref instead of not calling it at all?
template<class F, class...Ts> F for_each_arg(F f, Ts&&...a) {
return (void)initializer_list<int>{(ref(f)((Ts&&)a), 0)...}, f;
// why not return (void)initializer_list<int>{(f((Ts&&)a), 0)...}, f;
}
Upvotes: 10
Views: 952
Reputation: 42564
std::reference_wrapper::operator()
performs a bit of "magic" in some cases beyond what a direct function call would. Its effects are specified as (quoting N4296 [refwrap.invoke]):
template <class... ArgTypes> result_of_t<T&(ArgTypes&&... )> operator()(ArgTypes&&... args) const;
Returns:
INVOKE(get(), std::forward<ArgTypes>(args)...)
. (20.9.2)
where get()
returns a reference to what the reference_wrapper
wraps. INVOKE
is described in 20.9.2 [func.require]:
Define
INVOKE(f, t1, t2, ..., tN)
as follows:(1.1) —
(t1.*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;(1.2) —
((*t1).*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is not one of the types described in the previous item;(1.3) —
t1.*f
whenN == 1
andf
is a pointer to member data of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;(1.4) —
(*t1).*f
whenN == 1
andf
is a pointer to member data of a classT
andt1
is not one of the types described in the previous item;(1.5) —
f(t1, t2, ..., tN)
in all other cases.
The result of calling ref(f)
instead of simply f
is that pointer-to-member-function and pointer-to-member-data can be "called" with an appropriate object pointer/reference as parameter. For example,
struct A { void foo(); };
struct B : A {};
struct C : B {};
for_each_arg(&A::foo, A{}, B{}, C{}, std::make_unique<A>());
would call foo
on the A
, B
and C
temporary objects and the object held in the unique_ptr
(DEMO). Why one would prefer to use ref(f)
over f
would obviously depend on the context in which one is using for_each_arg
.
Upvotes: 17