2013-05-14 12 views
5

मैं एक बड़ी कक्षा को पुन: सक्रिय करने की प्रक्रिया में हूं - चलो इसे Big पर कॉल करें - इसमें बड़ी संख्या में कॉपी-पेस्ट कोड है। इस कॉपी-पेस्ट कोड में से अधिकांश switchcase एस में मौजूद है जहां केवल शामिल प्रकार अलग-अलग होते हैं। यह कोड कक्षा के enum सदस्य चर के आधार पर स्विच कर रहा है जिसका मूल्य केवल रनटाइम पर जाना जाता है।टेम्पलेट पैरामीटर के साथ सी ++ फ़ंक्शन प्रेषण

इसमें सुधार करने का मेरा प्रयास कक्षा है जिसमें static फ़ंक्शन के माध्यम से lookup() नामक उचित टाइप किए गए फ़ंक्शन दिखते हैं। वास्तविक कार्य करने वाले फ़ंक्शंस को हमेशा go() कहा जाता है और उन्हें एक रैपर क्लास टेम्पलेट में परिभाषित किया जाना चाहिए (जिसका एकमात्र पैरामीटर रनटाइम enum वर्तमान में चालू होने वाला मान है)। go() फ़ंक्शन टेम्पलेट फ़ंक्शन स्वयं हो सकते हैं या नहीं भी हो सकते हैं।

यहां कोड का एक आसवित संस्करण है। लंबाई के लिए मेरी माफ़ी, लेकिन यह उतना छोटा था जितना कि मैं इसे महत्वपूर्ण संदर्भ खोने के बिना प्राप्त कर सकता था।

#include <cassert> 

class Big 
{ 
    public: 

     enum RuntimeValue { a, b }; 

     Big(RuntimeValue rv) : _rv(rv) { } 

     bool equals(int i1, int i2) 
     { 
      return Dispatcher<Equals, bool(int, int)>::lookup(_rv)(i1, i2); 
     } 

     template<typename T> 
     bool isConvertibleTo(int i) 
     { 
      return Dispatcher<IsConvertibleTo, bool(int)>::lookup<T>(_rv)(i); 
     } 

    private: 

     template<RuntimeValue RV> 
     struct Equals 
     { 
      static bool go(int i1, int i2) 
      { 
       // Pretend that this is some complicated code that relies on RV 
       // being a compile-time constant. 
       return i1 == i2; 
      } 
     }; 

     template<RuntimeValue RV> 
     struct IsConvertibleTo 
     { 
      template<typename T> 
      static bool go(int i) 
      { 
       // Pretend that this is some complicated code that relies on RV 
       // being a compile-time constant. 
       return static_cast<T>(i) == i; 
      } 
     }; 

     template<template<RuntimeValue> class FunctionWrapper, typename Function> 
     struct Dispatcher 
     { 
      static Function * lookup(RuntimeValue rv) 
      { 
       switch (rv) 
       { 
        case a: return &FunctionWrapper<a>::go; 
        case b: return &FunctionWrapper<b>::go; 

        default: assert(false); return 0; 
       } 
      } 

      template<typename T> 
      static Function * lookup(RuntimeValue rv) 
      { 
       switch (rv) 
       { 
        case a: return &FunctionWrapper<a>::go<T>; 
        case b: return &FunctionWrapper<b>::go<T>; 

        default: assert(false); return 0; 
       } 
      } 

      // And so on as needed... 
      template<typename T1, typename T2> 
      static Function * lookup(RuntimeValue rv); 
     }; 

     RuntimeValue _rv; 
}; 

int main() 
{ 
    Big big(Big::a); 

    assert(big.equals(3, 3)); 
    assert(big.isConvertibleTo<char>(123)); 
} 

यह ज्यादातर, काम करता है सिवाय इसके कि:

  1. यह बनाता है और विजुअल C++ 9 (2008) के तहत ठीक काम करता है, लेकिन जीसीसी 4.8 के तहत यह lookup() का कार्य-टेम्पलेट अधिभार में संकलन त्रुटियों में परिणाम ।
  2. यह आवश्यक है कि lookup() का एक नया फ़ंक्शन-टेम्पलेट अधिभार go() में समर्थन करने के लिए हर नए फ़ंक्शन टेम्पलेट पैरामीटर के लिए लिखा जाए।
  3. यह बोझिल और उपयोग करने में भ्रमित है।

    Big.cpp: In static member function 'static Function* Big::Dispatcher<FunctionWrapper, Function>::lookup(Big::RuntimeValue)': 
    Big.cpp(66,65) : error: expected primary-expression before '>' token 
             case a: return &FunctionWrapper<a>::go<T>; 
                       ^
    Big.cpp(66,66) : error: expected primary-expression before ';' token 
             case a: return &FunctionWrapper<a>::go<T>; 
                       ^
    Big.cpp(67,65) : error: expected primary-expression before '>' token 
             case b: return &FunctionWrapper<b>::go<T>; 
                       ^
    Big.cpp(67,66) : error: expected primary-expression before ';' token 
             case b: return &FunctionWrapper<b>::go<T>; 
                       ^
    

    मेरा प्रश्न दोहरा है::

यहाँ त्रुटियों कि जीसीसी के अंतर्गत होने वाली हैं

  1. क्यों इस जीसीसी के तहत निर्माण करने के लिए विफल हो रहा है, और मैं इसे कैसे ठीक करूं?
  2. क्या ऐसा करने के लिए कोई बेहतर (यानी, कम बोझिल और भ्रमित) तरीका है?

कोड को दृश्य सी ++ 9 (2008) के तहत संकलित करने योग्य है, इसलिए मैं कुछ भी C++ 11-विशिष्ट का उपयोग नहीं कर सकता।

case a: return &FunctionWrapper<a>::template go<T>; 
//         ^^^^^^^^ 
case b: return &FunctionWrapper<b>::template go<T>; 
//         ^^^^^^^^ 

इस संकलक क्या एक टेम्पलेट के नाम के रूप में गुंजाइश संकल्प ऑपरेटर (::) इस प्रकार पार्स करने के लिए कहता है:

उत्तर

6

के बाद से go एक टेम्पलेट के एक आश्रित नाम है, तो आप template disambiguator उपयोग करने की आवश्यकता , और बाद के कोणीय ब्रैकेट टेम्पलेट तर्क के लिए delimiters के रूप में।

यह जीसीसी के तहत निर्माण करने में विफल क्यों है, और मैं इसे कैसे ठीक कर सकता हूं?

जीसीसी मानक के अनुरूप है, और two-phase name lookup करता है, जबकि MSVC इन्स्टेन्शियशन समय तक नाम देखने विलंब और इसलिए, कोई जानता है कि go एक टेम्पलेट का नाम है क्योंकि।

इन्स्टेन्शियशन से पहले इस जानकारी उपलब्ध नहीं है, क्योंकि यह पता है कि T है असंभव है, और प्राथमिक टेम्पलेट किसी दिए गए T तो के लिए विशेष जा सकता है कि go एक सदस्य समारोह टेम्पलेट का नाम नहीं है, बल्कि एक की डेटा सदस्य

यह कहा गया है कि, मैं उम्मीद करता हूं कि एमएसवीसी template असंबद्धता का समर्थन करने के लिए किसी भी तरह से समर्थन करेगी, इसलिए इसे आपके प्रोग्राम को जीसीसी/क्लैंग/जो भी-अनुरूप-मानक और एमएसवीसी पर संकलित करना चाहिए।

+0

आपके उत्तर के लिए धन्यवाद। क्या आपके पास मेरे प्रश्न के दूसरे भाग के बारे में कोई सलाह है? हालांकि यह योजना काम करती है (आपकी मदद के लिए धन्यवाद), मैं इसके साथ वास्तव में खुश नहीं हूं। मैंने एक विकल्प के रूप में आभासी कार्यों का उपयोग करके खोज की, लेकिन मैंने एक ईंट की दीवार मारा जब मुझे एहसास हुआ कि इसके लिए वर्चुअल फ़ंक्शन टेम्पलेट्स की आवश्यकता होगी, जो C++ का समर्थन नहीं करता है। – Spire

+0

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

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