2016-03-10 6 views
5

क्या इस से Finalizer कक्षा लिखने का कोई और सामान्य तरीका है?मैन्युअल क्लास टेम्पलेट पैरामीटर विनिर्देश से छुटकारा पाने के लिए कैसे करें

Finalizer finalizer([]() { std::cout << "str" << std::endl; }); 

क्या यह संभव है:

#include <functional> 
#include <iostream> 

template <typename T> 
class Finalizer 
{ 
public: 
    Finalizer(const std::function<T>& f) : _f(f) {} 

    ~Finalizer() 
    { 
     _f(); 
    } 

private: 
    std::function<T> _f; 
}; 

int main() 
{ 
    Finalizer<void()> finalizer([]() { std::cout << "str" << std::endl; }); 
} 

मैं चाहता हूँ इस तरह कोड लिखने के लिए सक्षम होने के लिए मैनुअल वर्ग टेम्पलेट पैरामीटर विनिर्देश से छुटकारा पाने के लिए?

+0

सीधे क्यों नहीं लिख 'std :: समारोह '? या एक डिफ़ॉल्ट टेम्पलेट पैरामीटर 'टाइपनाम टी = शून्य() 'दे? – Garf365

+0

@ Garf365 अधिक सामान्य होने के लिए। कुछ फ़ाइनलाइज़र विधियां वास्तव में एक अलग फ़ंक्शन हो सकती हैं जो त्रुटि कोड वापस कर सकती हैं लेकिन मैं उन्हें 'फाइनलाइज़र' कक्षा में किसी भी तरह से उपयोग करना चाहता हूं और ऐसी स्थितियों में उनके त्रुटि कोड को अनदेखा कर सकता हूं – FrozenHeart

+0

@ फ्रोजनहेर्ट 'std :: function ' का उपयोग करके स्वचालित रूप से अनदेखा हो जाएगा परिणाम, यहां कोई समस्या नहीं है। – lisyarus

उत्तर

5

सी ++ प्रकार में कटौती केवल फ़ंक्शन टेम्पलेट्स के लिए उपलब्ध है, क्लास टेम्पलेट्स के लिए नहीं। आपको टेम्पलेट तर्क कटौती करने के लिए make_finalizer फ़ंक्शन की आवश्यकता है।

इसके अलावा आपको std::function का उपयोग करने की आवश्यकता नहीं है, रनटाइम लागत के लिए भुगतान करने की कोई आवश्यकता नहीं है, जब तक कि आप वास्तव में इसे टाइप-मिस्ड नहीं करना चाहते।

template <typename F> 
class Finalizer 
{ 
public: 
    Finalizer(const F & c) : f_(c) {} 
    Finalizer(F && c) : f_(std::move(c)) {} 
    Finalizer(const Finalizer &) = delete; 
    Finalizer(Finalizer && other) : 
      valid_(other.valid), 
      f_(std::move(other.f_)) 
    { 
     other.valid_ = false; 
    } 

    Finalizer& operator=(const Finalizer &) = delete; 
    Finalizer& operator=(Finalizer && other) 
    { 
     Finalizer tmp(std::move(other)); 
     swap(tmp); 
     return *this; 
    } 

    ~Finalizer() 
    { 
     if (valid_) 
      f_(); 
    } 

    void swap(Finalizer & other) noexcept 
    { 
     using std::swap; 
     swap(other.valid_, valid_); 
     swap(other.f_, f_); 
    } 

private: 
    bool valid_ = true; 
    F f_; 
}; 

template<class F> 
Finalizer< std::remove_reference_t<F> > at_scope_exit(F && x) 
{ 
    return Finalizer< std::remove_reference_t<F> >(std::forward<F>(x)); 
} 

और ऑटो के साथ उपयोग करें:

auto x = at_scope_exit([]() { std::cout << "Hello world" << std::endl; }); 
+0

मुझे यहां 'std :: forward' कॉल क्यों चाहिए? – FrozenHeart

+0

@ फ्रोजनहेर्ट क्योंकि आप इसे ले जाने के बजाय लैंबडा को 'फाइनलाइज़र' के अंदर कॉपी करना चाहते हैं। – sbabbi

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

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