2014-10-13 4 views
4

꼭 필요한 경우에만 펑터 콜을 전달하고 그 펑터를 복사하고 싶습니다.최소한의 복사를 담당하는 전방 펑터

template <typename F> 
void wrapper (F func) 
{ 
    func(); 
} 

struct Functor 
{ 
    Functor() {} 
    void operator()() { /* do some work */ } 
}; 

내가 호출 할 수있는 래퍼를 rvalue 참조

  1. 과 : 여기 내 일반적인 래퍼 함수와 펑입니다 래퍼는 (은 Functor());
  2. 왼쪽 값 : Functor f; 래퍼 (f);
  3. const 왼쪽 값 참조 : const Functor f; 래퍼 (f);
  4. const rvalue reference : const Functor make_functor(); 래퍼 (make_functor());

const 참조가 전달 된 경우에만 래퍼의 arg를 복사하려고합니다.

using safe_mutual_handler_type = 
    typename std::conditional< 
    std::is_reference<F>::value 
    , typename std::conditional< 
     std::is_const<typename std::remove_reference<F>::type>::value 
    , typename std::remove_const<typename std::remove_reference<F>::type>::type 
    , F& 
    >::type 
    , F& 
    >::type; 

template <typename F> 
void wrapper (F&& func) 
{ 
    safe_mutual_handler_type<F> tmp = func; 
    tmp(); 
} 

아주 좋은 및 누락되지 않음 (매우 전형적인되지 않음) const를-를 rvalue 참조 사건을하지만, 기본적으로 작업을 수행 그래서 나는 그런 래퍼 구현에 온다.

그러나 나는 또한 CONST 연산자()

struct Functor { 
    Functor() {} 
    void operator()() const {} 
}; 

와 내가 모든 래퍼의 인수를 복사 할 필요가없는 경우에은 Functor가있을 수 있습니다.

질문은 다음과 같습니다. Functor에는 상수 괄호 연산자가 있습니까? 또 다른 질문은 래퍼이 유형 특성의 typedef 라인의 막대한 수없이 더 똑똑하고 컴팩트 한 방법으로 구현 될 수 있다는 것입니다. (실제로 코드 크기가 아니라 코드 가독성에 대해 걱정하고 있습니다.)

답변

5

단순히 표현 SFINAE을 그들과 함께 호출이 유효한 경우, 참조를 사용하여 사용하려는 경우 :

template <typename F> 
auto wrapper_ (F&& func, int) -> decltype(func()) 
{ 
    func(); 
} 

template <typename F> 
void wrapper_ (F func, ...) 
{ 
    func(); 
} 

template <typename F> 
void wrapper (F&& f) 
{ 
    wrapper_(std::forward<F>(f), 0); 
} 

만 복사하려면/당신이 (단지 다음과) 변경 가능한 참조를 통과 할 때 이동 :

template <typename F> 
auto wrapper_ (F&& func, std::true_type) 
{ 
    func(); 
} 

template <typename F> 
void wrapper_ (F func, std::false_type.) 
{ 
    func(); 
} 

template <typename F> 
void wrapper (F&& f) 
{ 
    wrapper_(std::forward<F>(f), std::is_const<typename std::remove_reference<F>::type>()); 
}