为什么人们更愿意调用std :: ref而不是根本不调用它?
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;
}
答案 0 :(得分:17)
std::reference_wrapper::operator()
执行了一些&#34;魔法&#34;在某些情况下,超出直接函数调用的范围。其效果指定为(引用N4296 [refwrap.invoke]):
template <class... ArgTypes> result_of_t<T&(ArgTypes&&... )> operator()(ArgTypes&&... args) const;
返回:
INVOKE(get(), std::forward<ArgTypes>(args)...)
。 (20.9.2)
其中get()
返回对reference_wrapper
包装内容的引用。 INVOKE
在20.9.2 [func.require]中描述:
如下定义
INVOKE(f, t1, t2, ..., tN)
:(1.1) -
(t1.*f)(t2, ..., tN)
当f
是指向类T
的成员函数的指针时,t1
是T
类型的对象或对T
类型的对象的引用或对从T
派生的类型的对象的引用;(1.2) -
((*t1).*f)(t2, ..., tN)
当f
是指向类T
的成员函数的指针时,t1
不是上一项中描述的类型之一;(1.3) -
t1.*f
当N == 1
和f
是指向类T
的成员数据的指针时,t1
是T
类型的对象{1}}或对T
类型对象的引用或对T
派生类型的对象的引用;(1.4) -
(*t1).*f
当N == 1
和f
是指向类T
的成员数据的指针时,t1
不是其中一种类型在前一项中描述;(1.5) -
f(t1, t2, ..., tN)
在所有其他情况下。
调用ref(f)
而不是简单f
的结果是指向成员函数的指针和指向成员的指针数据可以被称为&#34;&#34;使用适当的对象指针/引用作为参数。例如,
struct A { void foo(); };
struct B : A {};
struct C : B {};
for_each_arg(&A::foo, A{}, B{}, C{}, std::make_unique<A>());
会在foo
,A
和B
临时对象以及C
(DEMO)中保留的对象上调用unique_ptr
。为什么更喜欢使用ref(f)
超过f
显然取决于使用for_each_arg
的上下文。