2016-10-31 5 views
18

वैराडिक टेम्पलेट्स के बहुत सारे फायदे हैं, लेकिन क्या ऐसे अवसर हैं जब सी-स्टाइल वेरिएडिक फ़ंक्शन (<cstdarg> का उपयोग करके) का उपयोग किया जाना चाहिए?क्या कोई ऐसा मामला है जहां वैरिएबल फ़ंक्शंस को वैरिएडिक टेम्पलेट्स पर प्राथमिकता दी जानी चाहिए?

उत्तर

24
  1. यदि आप सी ++ कार्यान्वयन के साथ सी एपीआई प्रदान करते हैं, तो टेम्पलेट एपीआई के लिए एक विकल्प नहीं हैं। Varargs हैं।

  2. यदि आपको एक ऐसे कंपाइलर का समर्थन करने की आवश्यकता है जो सी ++ 11 या नए मानक का समर्थन नहीं करता है, तो वैरैडिक टेम्पलेट उपलब्ध नहीं हैं। Varargs हैं।

  3. यदि आपको फ़ायरवॉल संकलन की आवश्यकता है। अर्थात। आपको हेडर से फ़ंक्शन के कार्यान्वयन को छिपाने की आवश्यकता है, फिर विविध टेम्पलेट एक विकल्प नहीं है। Varargs हैं।

  4. मेमोरी बाधित सिस्टम (एम्बेडेड) पर, टेम्पलेट द्वारा उत्पन्न विभिन्न फ़ंक्शन बहुत अधिक ब्लोट पेश कर सकते हैं। उस ने कहा, इस तरह के सिस्टम आम तौर पर वास्तविक समय भी होते हैं, इस मामले में शाखाओं और ढेर के उपयोग के कारण वर्गार्ज भी अस्वीकार्य हो सकता है।

+10

varargs भी अधिभार संकल्प पर अंतिम विचार किया जा रहा की उनकी संपत्ति की वजह से कुछ metaprogramming (लक्षण उदाहरण के लिए SFINAE के साथ लागू) में किया जाता है। – bolov

+0

@ बोल्व शांत! मैंने उस मामले का कभी सामना नहीं किया है। ध्वनि थोड़ा * मेरे अच्छे हालांकि :) – user2079303

+0

@bolov के लिए भी * चालाक आप अधिक विवरण, यहां तक ​​कि कोड उदाहरण या लिंक –

14

मैं अधिभार संकल्प पर अंतिम विचार किया जा रहा की उनकी संपत्ति की वजह से भी कुछ metaprogramming (लक्षण उदाहरण के लिए SFINAE के साथ लागू) में किया जाता है excellent answer of @user2079303

varargs में जोड़ना चाहते हैं।

मान लीजिए कि हम पता लगाने के लिए एक विशेषता को लागू करना चाहते हैं तो एक वर्ग कुछ प्रकार से constructible में है (कुछ std::is_constructible की तरह:

एक सरलीकृत आधुनिक कार्यान्वयन (यह एक ही रास्ता नहीं है इस तरह जाना होगा: के रूप में कहा, void_t भी be used to implement the trait और जल्द ही (? 2020) हम इन चालबाज़ियों से किसी की जरूरत नहीं होगी कर सकते हैं के रूप में concepts एक प्रथम श्रेणी नागरिक के रूप में require खंड) के साथ अपने रास्ते पर हैं:

template <class T, class... Args> struct Is_constructible { 

    template <class... Params> 
    static auto test(Params... params) -> decltype(T{params...}, std::true_type{}); 

    static auto test(...) -> std::false_type; 

    static constexpr bool value = decltype(test(std::declval<Args>()...))::value; 
}; 

यह SFINAE की वजह से काम करता है: जब तत्काल एनजी test, अगर कुछ dependent name के कारण अर्थशास्त्र अमान्य हैं, तो यह एक कठिन त्रुटि नहीं है, इसके बजाय ओवरलोड को अनदेखा किया जाता है।

यदि आप लक्षणों की चाल के बारे में अधिक जानना चाहते हैं और वे कैसे कार्यान्वित होते हैं और वे कैसे काम करते हैं, तो आप आगे पढ़ सकते हैं: sfinae idiom, member detector idiom, enable_if idiom

तो, एक प्रकार X केवल 2 ints से निर्माण किया जा सकता है के साथ:

struct X { X(int, int) {}; }; 

हम ये परिणाम प्राप्त:

Is_constructible<X, int, int>::value // true 
Is_constructible<X, int>::value;  // false 

सवाल अब है कि क्या हम साथ varargs परीक्षण की जगह ले सकता वैरैडिक टेम्पलेट्स:

template <class T, class... Args> struct Is_constructible_broken { 

    template <class... Params> 
    static auto test(Params... params) -> decltype(T{params...}, std::true_type{}); 

    template <class... Params> 
    static auto test(Params...) -> std::false_type; 

    static constexpr bool value = decltype(test(std::declval<Args>()...))::value; 
}; 

और उत्तर नहीं है (कम से कम नहीं टी प्रत्यक्ष प्रतिस्थापन)।जब हम

Is_constructible_broken<X, int, int>::value 

का दृष्टांत हम कोई त्रुटि मिलती है:

error: call of overloaded ' test(int, int) ' is ambiguous

क्योंकि दोनों भार के व्यवहार्य हैं और दोनों एक ही "रैंक" अधिभार संकल्प में है। Varargs के साथ पहला कार्यान्वयन काम करता है क्योंकि भले ही दोनों अधिभार व्यवहार्य हैं, वैरिएड टेम्पलेट को vararg एक पर प्राथमिकता दी जाती है।

ऐसा लगता है कि आप वास्तव में यह variadic टेम्पलेट्स के साथ काम कर सकते हैं। चाल पहले अधिभार के लिए एक आदर्श मैच और दूसरे के लिए कोई रूपांतरण होता है कि test एक कृत्रिम पैरामीटर जोड़ने के लिए है:

struct overload_low_priority{}; 
struct overload_high_priority : overload_low_priority {}; 

template <class T, class... Args> struct Is_constructible2 { 

    template <class... Params> 
    static auto test(overload_high_priority, Params... params) 
     -> decltype(T{params...}, std::true_type{}); 

    template <class... Params> 
    static auto test(overload_low_priority, Params...) -> std::false_type; 

    static constexpr bool value 
     = decltype(test(overload_high_priority{}, std::declval<Args>()...))::value; 
}; 

लेकिन मुझे लगता है varargs इस मामले में और अधिक स्पष्ट है।

+0

ध्यान दें कि 'void_t' का उपयोग इलिप्सिस के उपयोग के बजाय गुण बनाने के लिए किया जा सकता है। – Jarod42

+0

@ Jarod42 हाँ, और जल्द ही है कि [आवश्यकता खंड] द्वारा भी अप्रचलित हो जाएगा (http://en.cppreference.com/w/cpp/language/constraints) – bolov

+0

मैं पसंद 'struct high_overload_priority: low_overload_priority {};' उपयोग ओवरलोड को ऑर्डर करने के लिए 'int' /' long' पर। – Jarod42

3

vararg __attribute__ format का उपयोग कर सकते हैं। जैसे

void debug(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 

void f(float value) 
{ 
    debug("value = %d\n", value); // <- will show warning. 
} 

दुर्भाग्य से यह विविध टेम्पलेट का उपयोग करके हासिल नहीं किया जा सकता है।

संपादित: जैसा कि व्लादिमीर ने बताया, मैं उल्लेख करना भूल गया कि __attribute__ format मानक का हिस्सा नहीं है, हालांकि यह जीसीसी और क्लैंग (लेकिन विजुअल स्टूडियो नहीं) दोनों द्वारा समर्थित है। अधिक जानकारी के लिए कृपया देखें: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes

+0

मैं आपको __attribute__ प्रारूप के उपयोग को जोड़ने का सुझाव दूंगा क्योंकि यह मानक में नहीं है। मुझे यह भी लगता है कि इसका उपयोग करने वाले कुछ कंपाइलरों को दिखाना अच्छा होता है। मुझे केवल जीसीसी पता है। –

+0

https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html –

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

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