std::reference_wrapper::operator()
thực hiện một chút "ma thuật" trong một số trường hợp ngoài cuộc gọi hàm trực tiếp. ảnh hưởng của nó được quy định như (trích dẫn 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)
nơi get()
trả về tham chiếu đến những gì reference_wrapper
kết thúc tốt đẹp. INVOKE
được mô tả trong 20.9.2 [func.require]:
Xác định INVOKE(f, t1, t2, ..., tN)
như sau:
(1,1) - (t1.*f)(t2, ..., tN)
khi f
là một con trỏ tới một hàm thành viên của một lớp T
và t1
là một đối tượng thuộc loại T
hoặc tham chiếu đến đối tượng thuộc loại T
hoặc tham chiếu đến đối tượng thuộc loại bắt nguồn từ T
;
(1,2) - ((*t1).*f)(t2, ..., tN)
khi f
là một con trỏ tới một hàm thành viên của một lớp T
và t1
không phải là một trong những loại được mô tả trong mục trước;
(1,3) - t1.*f
khi N == 1
và f
là một con trỏ đến dữ liệu thành viên của một lớp T
và t1
là một đối tượng kiểu T
hoặc một tham chiếu đến một đối tượng kiểu T
hoặc một tham chiếu đến một đối tượng của một loại có nguồn gốc từ T
;
(1,4) - (*t1).*f
khi N == 1
và f
là một con trỏ đến dữ liệu thành viên của một lớp T
và t1
không phải là một trong những loại được mô tả trong mục trước;
(1.5) - f(t1, t2, ..., tN)
trong tất cả các trường hợp khác.
Kết quả của việc gọi ref(f)
thay vì chỉ đơn giản là f
là con trỏ-to-viên-chức năng và con trỏ-to-viên-dữ liệu có thể "gọi là" với một con trỏ đối tượng/tài liệu tham khảo phù hợp theo tham số. Ví dụ,
struct A { void foo(); };
struct B : A {};
struct C : B {};
for_each_arg(&A::foo, A{}, B{}, C{}, std::make_unique<A>());
sẽ gọi foo
trên A
, B
và C
đối tượng tạm thời và các đối tượng tổ chức tại unique_ptr
(DEMO). Tại sao một người sẽ thích để sử dụng ref(f)
hơn f
rõ ràng sẽ phụ thuộc vào ngữ cảnh trong đó một người đang sử dụng for_each_arg
.
Không cần thiết. https://twitter.com/ericniebler/status/559798611991879684 – inf