2013-07-19 2 views
9

이전에는 함수 호출이 신속하게 확인하고 싶을 때마다 매크로를 사용하여 측정했습니다. 이제 가능한 C++ 11, 나는 마지막으로이 같은 뭔가 처리기 코드의 추악한 평화를 제거하고 교체하고 싶습니다 : 뭔가 (즉하지 void)을 반환하는 함수에 대해 잘 작동void 및 non-void 반환 함수에 대한 완벽한 전달

template <typename Functor, typename ... Args> 
auto measure(Functor f, Args && ... args) 
    -> decltype(f(std::forward<Args>(args)...)) 
{ 
    auto now = std::chrono::high_resolution_clock::now(); 
    auto ret = f(std::forward<Args>(args)...); 
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
     std::chrono::high_resolution_clock::now() - now).count(); 
    std::cout << "Time elapsed: " << elapsed << "ms" << std::endl; 

    return ret; 
} 

합니다. 그래서 void 함수에 과부하가 필요하다고 느꼈으 나 반환 유형에만 함수를 오버로드 할 수는 없습니다.

나는이 템플릿을 사용하여이 문제를 해결하려고 노력했지만 아무 소용이 없었다.

template < 
    typename Functor, typename ... Args, 
    typename ReturnType = typename std::enable_if< 
     !std::is_void< 
      typename std::result_of<Functor(Args...)>::type 
     >::value, 
     typename std::result_of<Functor(Args...)>::type 
    >::type 
> 
ReturnType measure(Functor f, Args && ... args) 
{ 
    auto now = std::chrono::high_resolution_clock::now(); 
    auto ret = f(std::forward<Args>(args)...); 
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
     std::chrono::high_resolution_clock::now() - now).count(); 
    std::cout << "Time elapsed: " << elapsed << "ms" << std::endl; 

    return ret; 
} 

template < 
    typename Functor, typename ... Args, 
    typename ReturnType = typename std::enable_if< 
     std::is_void< 
      typename std::result_of<Functor(Args...)>::type 
     >::value 
    >::type 
> 
ReturnType measure(Functor f, Args && ... args) 
{ 
    auto now = std::chrono::high_resolution_clock::now(); 
    f(std::forward<Args>(args)...); 
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
     std::chrono::high_resolution_clock::now() - now).count(); 
    std::cout << "Time elapsed: " << elapsed << "ms" << std::endl; 
} 

이 주위에 방법이 있나요 : 컴파일러는 여전히 기능 measure가 두 번 정의 불평?

template <typename Functor, typename ... Args> 
auto measure(Functor f, Args && ... args) 
    -> decltype(f(std::forward<Args>(args)...)) 
{ 
    struct scoped_timer 
    { 
     scoped_timer() : now_(std::chrono::high_resolution_clock::now()) {} 
     ~scoped_timer() 
     { 
      auto elapsed = std::chrono::duration_cast< 
        std::chrono::milliseconds 
       >(std::chrono::high_resolution_clock::now() - now_).count(); 
      std::cout << "Time elapsed: " << elapsed << "ms" << std::endl; 
     } 

     private: 
      std::chrono::high_resolution_clock::time_point const now_; 
    } scoped_timer; 

    return f(std::forward<Args>(args)...); 
} 
+0

http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html#evolution –

+0

우아한 [아이디어] (http://stackoverflow.com/a/17748197/1137388) ([R. Martinho Fernandes] (http://stackoverflow.com/users/46642/r-martinho-fernandes)). 유일한 변경은 '~ scoped_timer()'의 코드를'try-catch' 블록에 넣는 것입니다. 의미 상으로는,'f'가 성공적으로 완료되지 않으면 실행되는 시간을보고하지 않는 것이 합리적이라고 생각합니다. 불행하게도 이것은'<< "에 의해 던져 질 가능성이있는 예외에 대해서는 그리 명백하지 않습니다. 오래된'printf'가 (예외 안전에 관한) 더 나은 대안이 될 것입니까? 나는 모른다. –

답변

14

문제는 기본 템플릿 인수가 다른 템플릿을하지 않는다는 것입니다 : 여기에 UPDATE


는 R. 마르틴 페르난데스에게 지금 감사를 사용하고있는 기능입니다 같은 방식으로 기본 함수 인수가 서로 다른 오버로드에 적용되지 않습니다. 이 문제를 해결하기위한 몇 가지 방법이 있으며, 내 Remastered enable_if 문서에서 설명했습니다.

그러나 나는 그렇게하지 않을 것입니다. 단순히 일반적인 코드는 "return 무효"및 경과 시간을 인쇄 할 RAII를 사용할 수 있다는 사실을 이용할 것이다 :

scoped_timer 클래스가 사소하게 쓸 수
template <typename Functor, typename ... Args> 
auto measure(Functor f, Args && ... args) 
    -> decltype(f(std::forward<Args>(args)...)) 
{ 
    scoped_timer timer; 
    return f(std::forward<Args>(args)...); 
} 

: 생성자에서 now을 저장, 소멸자에 elapsed을 계산하여 출력하십시오.

+0

사실, 전에 이와 비슷한 작업을 수행했으며 결과 값을 모두 삭제했으며 대신'measure'가 경과 시간을 반환했습니다. –

+0

당신의 기사는 믿을 수 없을만큼 재미 있습니다. 고맙습니다. 함수가 원래 반환하는 값을 여전히 반환하고 싶습니다. 그러나이 경우 솔루션이 제대로 작동합니다. – user2573221

관련 문제