2016-04-16 6 views
7

उत्सुकता से आवर्ती टेम्पलेट पैटर्न का उपयोग एक प्रकार के स्थैतिक बहुरूपता को लागू करने के लिए किया जा सकता है। उदाहरण के लिए:सीआरटीपी - आधार वर्ग से जांच कर रहा है कि व्युत्पन्न व्यक्ति

#include <iostream> 

template< 
class Derived 
> 
struct Base 
{ 
    static void print () 
    { 
     std::cout << Derived::number_to_print << '\n'; 
    } 
}; 

struct Derived final : 
    Base< 
    Derived 
    > 
{ 
    static constexpr unsigned int number_to_print = 27; 
}; 

int main () 
{ 
    Derived::print(); 
} 

इस रूप में की उम्मीद और प्रिंट 27 व्यवहार करता है।

अब, मैं आधार वर्ग के लिए जाँच करता है जोड़ने के लिए जोर देने के लिए है कि व्युत्पन्न वर्ग कुछ आवश्यकताओं को पूरा करना चाहते हैं। ऊपर दिए गए उदाहरण में, इस तरह की जांच हो सकता है:

#include <iostream> 
#include <type_traits> 

template< 
class Derived 
> 
struct Base 
{ 
    // --- Checks begin 
    static_assert(std::is_same< 
     decltype(Derived::number_to_print), 
     unsigned int 
     >::value, 
     "static member `number_to_print' should be of type `unsigned int'"); 
    // --- Checks end 

    static void print () 
    { 
     std::cout << Derived::number_to_print << '\n'; 
    } 
}; 

struct Derived final : 
    Base< 
    Derived 
    > 
{ 
    static constexpr unsigned int number_to_print = 27; 
}; 

int main () 
{ 
    Derived::print(); 
} 

इस बिंदु जहां Base<Derived> instantiated है क्योंकि काम नहीं करता,, Derived केवल आगे की घोषित किया गया है, यानी, यह अधूरा है, और यह कुछ भी नहीं की अभी तक इस तथ्य से परे जाना जाता है कि यह एक संरचना है।

मैं अपने सिर खरोंच किया गया है, के रूप में मुझे लगता है कि इन चेकों आधार वर्ग के उपयोगकर्ताओं के लिए मददगार साबित हो सकता है, लेकिन किसी भी तरह से यह करने के लिए नहीं मिला है।

क्या यह संभव है ?, और यदि हां, तो कैसे?

+0

[इस पृष्ठ] (http://www.gotw.ca/publications/mxc++-item-4.htm) बहुत उपयोगी है। – Kalrish

उत्तर

4

noted by Kerrek SB के रूप में आप एक सदस्य समारोह के मुख्य भाग में स्थिर जोर स्थानांतरित कर सकते हैं।

और जब आप वर्तमान static सदस्य फ़ंक्शंस के बजाय कार्यक्षमता प्रदान करते हैं, तो वर्तमान static सदस्य फ़ंक्शन के बजाय, आप फ़ंक्शन बॉडी को कन्स्ट्रक्टर का बॉडी दे सकते हैं।

उदा।

#include <iostream> 
#include <type_traits> 
using namespace std; 

#define STATIC_ASSERT(e) static_assert(e, #e " // <- is required") 

template< class A, class B > 
constexpr auto is_same_() -> bool { return std::is_same<A, B>::value; } 

template< class Derived > 
struct Base 
{ 
    Base() 
    { 
     STATIC_ASSERT((
      is_same_< remove_cv_t< decltype(Derived::number_to_print) >, int >() 
      )); 
    } 

    void print() const 
    { 
     std::cout << Derived::number_to_print << '\n'; 
    } 
}; 

struct Derived final 
    : Base<Derived> 
{ 
    static constexpr int number_to_print = 27; 
}; 

auto main() 
    -> int 
{ 
    Derived::Base().print(); 
} 
3

एक गंदा चाल के रूप में, आप एक सदस्य समारोह के मुख्य भाग में स्थिर दावे को स्थानांतरित कर सकते हैं। चूंकि सदस्य फ़ंक्शन परिभाषा कक्षा परिभाषा के बाद तुरंत प्रभावी ढंग से दिखाई देती है, Derived का प्रकार सदस्य फ़ंक्शन बॉडी के अंदर पूरा हो जाता है।

खबरदार वर्ग टेम्पलेट्स के उस सदस्य कार्यों के लिए खुद को समारोह टेम्पलेट्स कर रहे हैं, और इस तरह वे केवल तभी इस्तेमाल किया instantiated कर रहे हैं (या वर्ग टेम्पलेट स्पष्ट रूप से instantiated है)।

+0

आदर्श रूप से, चेक का प्रयोग किया जाएगा भले ही कोई विधि उपयोग नहीं की गई हो। यदि यह संभव नहीं है और उन्हें सदस्य कार्यों के अंदर होना है, तो सबसे अच्छा मैं सोच सकता हूं कि उन्हें प्रत्येक सदस्य फ़ंक्शन से बुलाए गए एक निजी स्थिर 'constexpr' फ़ंक्शन में डाल दिया गया है, ताकि उन्हें डुप्लिकेट न किया जा सके। हालांकि सुरुचिपूर्ण नहीं है। – Kalrish

1

एक वैकल्पिक दृष्टिकोण के रूप में, आप एक निजी विधि का उपयोग कर सकते हैं (अन्य उत्तर वास्तव में बहुत अच्छी हैं) और sfinae पर भरोसा करते हैं:

#include <iostream> 
#include <type_traits> 

template<class Derived> 
struct Base { 
    static void print () { 
     print<Derived>(); 
    } 

private: 
    template<class D> 
    static 
    std::enable_if_t<std::is_same<std::remove_cv_t<decltype(D::N)>, unsigned int>::value> 
    print() { 
     std::cout << D::N << '\n'; 
    } 
}; 

struct Derived final: Base<Derived> { 
    static constexpr unsigned int N = 27; 
}; 

int main () { 
    Derived::print(); 
} 

इस तरह त्रुटि केवल उठता है अगर आप वास्तव में print का उपयोग करें।

+0

ठीक है, बिंदु उन त्रुटियों को जोड़ना था जो शुरुआती त्रुटियों को पकड़ते थे और स्पष्ट निदान जारी करते थे, इसलिए तथ्य यह है कि जांच तब होती है जब विधि तत्काल हो जाती है, बाधा है, लाभ नहीं है (यह समस्या स्थैतिक विधियों के साथ अपरिहार्य प्रतीत होती है; केवल @ चेयर 'रचनाकारों के साथ दृष्टिकोण इसे हल करता है)। इसके अलावा, आपका तरीका किसी भी स्पष्ट निदान की पेशकश नहीं करता है; समस्या संकलक त्रुटियों के भार में दफनाया जाएगा। – Kalrish

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