2015-01-26 3 views
10

왜 std :: ref를 호출하지 않고 대신 std :: ref를 호출해야합니까?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; 
} 
+2

필요하지 않습니다. https://twitter.com/ericniebler/status/559798611991879684 – inf

답변

17

std::reference_wrapper::operator()은 무엇 직접적인 함수 호출 것 이상으로 어떤 경우에는 "마법"의 비트를 수행합니다.

template <class... ArgTypes> 
result_of_t<T&(ArgTypes&&...)> 
operator()(ArgTypes&&... args) const; 

반환 : 그것의 효과는 (N4296 [refwrap.invoke]를 인용)로 지정됩니다 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)Tt1는 클래스의 멤버 함수에 대한 포인터 f이면 T 유형의 객체 또는 T 유형의 객체에 대한 참조 또는 T에서 파생 된 유형의 객체에 대한 참조;

(1.2) - ((*t1).*f)(t2, ..., tN)fTt1 이전에 기재된 유형의 하나가 아닌 클래스의 멤버 함수를 가리키는 포인터이고;

(1.3) - t1.*fN == 1fTt1T의 개체 또는 유형 T의 목적 또는 유도 된 타입의 객체에 대한 참조에 대한 참조는 클래스의 멤버 데이터에 대한 포인터이며 T에서;

(1.4) - (*t1).*fN == 1fTt1 이전에 기재된 유형의 하나가 아닌 클래스의 멤버 데이터에의 포인터 인 경우;

(1.5) - f(t1, t2, ..., tN) 다른 모든 경우에 해당합니다.

ref(f) 호출 대신에 단순히 f 결과

는 그 포인터 멤버 함수 부재 데이터가 가리키는 포인터 변수 같은 적절한 객체 포인터/참조하여 "호출"할 수있다. 예를 들어,

struct A { void foo(); }; 
struct B : A {}; 
struct C : B {}; 
for_each_arg(&A::foo, A{}, B{}, C{}, std::make_unique<A>()); 

A, BC 임시 개체에 foounique_ptr (DEMO)에서 개최 된 개체를 호출합니다. 왜 을 선호하는지 ref(f)f 이상으로 사용하는 것은 명백하게 for_each_arg을 사용하는 상황에 달려 있습니다.

+0

흥미롭고 또 다른 'std :: reference_wrapper'의 마법 같은 기능. 왜 Eric Niebler가 불필요하다고 생각하는지 궁금합니다. – inf

+0

@bamboon 더 많은 문맥없이 말하기가 어렵습니다.나는'ref()'가 5 개의 문자를 추가하고 그것을 제거함으로써 코드 골프 목적을 위해 더 짧은 코드를 결과한다고 추측한다. – Casey

+0

왜'auto f = std :: ref (& A :: foo);가 실패하지만'auto f = & A :: foo; 자동 f2 = std :: ref (f)'성공? – Barry

관련 문제