2013-07-19 10 views
9

पहले मैं जब भी मैं इसे तुरंत जांचना चाहता था तो एक फ़ंक्शन कॉल करने के समय को मापने के लिए मैक्रो का उपयोग कर रहा था। अब, के साथ सी ++ 11 उपलब्ध है, मैं अंत में पूर्वप्रक्रमक कोड की कि बदसूरत शांति को हटाने और कुछ इस तरह से बदलने के लिए करना चाहते हैं:शून्य और गैर-शून्य रिटर्निंग फ़ंक्शंस के लिए बिल्कुल सही अग्रेषण

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 नहीं) लौटने के लिए ठीक काम करता है। इसलिए मुझे लगा कि मुझे void फ़ंक्शंस के लिए ओवरलोड की आवश्यकता है - लेकिन आप केवल रिटर्न प्रकार पर फ़ंक्शन ओवरलोड नहीं कर सकते हैं।

मैंने कुछ टेम्पलेट जादू का उपयोग करके इस समस्या को हल करने की कोशिश की, लेकिन इसका कोई फायदा नहीं हुआ; संकलक अभी भी शिकायत है कि समारोह measure दो बार परिभाषित किया गया है:

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; 
} 

वहाँ इस के चारों ओर एक रास्ता नहीं है?

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) ([आर मार्टिन्हो फर्नांडीस] द्वारा (http://stackoverflow.com/users/46642/r-martinho-fernandes))। एकमात्र परिवर्तन जो मैं करूँगा वह 'try-catch' ब्लॉक में 'scoped_timer()' 'कोड को रखेगा जो किसी भी अपवाद को निगलता है। अर्थात्, मेरा मानना ​​है कि यह उस समय की रिपोर्ट नहीं करना समझता है जब 'f' को चलाने के लिए सफलतापूर्वक पूरा नहीं होता है। दुर्भाग्य से, यह '<<' द्वारा फेंक दिए गए संभावित अपवादों के बारे में इतना स्पष्ट नहीं है। क्या पुराना 'printf' बेहतर विकल्प होगा (अपवाद सुरक्षा के संबंध में)? मुझे नहीं पता। –

उत्तर

14

समस्या यह है कि डिफ़ॉल्ट टेम्पलेट तर्क अलग टेम्पलेट्स के लिए नहीं बनाते हैं है:


अद्यतन

यहाँ समारोह आर Martinho फर्नांडीस को मैं अब धन्यवाद का उपयोग कर रहा है , वही तरीका है कि डिफ़ॉल्ट फ़ंक्शन तर्क विभिन्न ओवरलोड के लिए नहीं बनाते हैं। इसके आसपास कुछ तरीके हैं, और मैंने उन्हें अपने Remastered enable_if आलेख में वर्णित किया है।

हालांकि, मैं ऐसा नहीं करूँगा। , निर्माता में now बचाने: मैं बस तथ्य का लाभ ले जाएगा कि जेनेरिक कोड में आप "return शून्य", और आरए II उपयोग कर सकते हैं बाहर लगे समय को मुद्रित करने के लिए:

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)...); 
} 

scoped_timer वर्ग तुच्छता से लिखा जा सकता है और विनाशक में elapsed गणना और आउटपुट।

+0

असल में, मैंने पहले ऐसा कुछ किया है, और मैंने परिणाम परिणाम को पूरी तरह से गिरा दिया है, इसके बजाय 'माप' के बजाय विलुप्त समय लौटा रहा है। –

+0

आपका लेख एक अविश्वसनीय रूप से दिलचस्प पढ़ा है। धन्यवाद। मैं अभी भी मूल रूप से रिटर्न के मूल्य को वापस करना चाहता हूं, लेकिन आपका समाधान इसके लिए ठीक काम करता है। – user2573221

संबंधित मुद्दे