2009-02-20 18 views
23

मस्तिष्क के फार्ट होने के बाद ... क्या इस काम की तरह कुछ करना संभव है?नेस्टेड टेम्पलेट विशेषज्ञता

template<int a> struct Foo 
{ 
    template<int b> struct Bar; 
}; 

template<int a> struct Foo<a>::Bar<1> //Trying to specialize Bar 
{ 
}; 

मैं नहीं यह करने के लिए है, लेकिन यह मुझे अच्छी तरह से नाम स्थान दायरे से कुछ कार्यान्वयन विवरण को छिपाने के लिए अनुमति देगा।

सुझावों की सराहना की!

पीएस .: मैं यह उल्लेख करना भूल गया कि फू के दायरे में बार के लिए स्पष्ट रूप से विशेषज्ञता के लिए भाषा द्वारा समर्थित नहीं है। AFAICS, वैसे भी।

उत्तर

3

इन पदों के अनुसार:

http://www.cpptalk.net/template-member-function-specialization-vt11666.html

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

+0

निराशाजनक। संदर्भ के लिए धन्यवाद, यद्यपि! –

+0

आईएसओ 14882: 1 99 8 धारा 14.7.3, अनुच्छेद 16 वह है जो इस स्थिति का वर्णन करता है। – greyfade

0

आप ' ऐसा मत करो। मैंने कई बदलावों की कोशिश की है। यह, तथापि, जीसीसी 4.1 में संकलित:

template<int a> struct Foo 
{ 
    template<int b> struct Bar; 
    template<1> struct Bar; 
}; 

संपादित करें (मानक की समीक्षा के बाद): तो एक दिया जाता है, हालांकि, आप यह कर सकते हैं:

template <> template <> Foo<1> Bar<1>; 

लेकिन अगर नहीं फू पहले विशेष नहीं है।

12

हाँ, आप कर सकते हैं। लेकिन आपको कॉल स्ट्रक्चर को बदलने की आवश्यकता होगी, लेकिन थोड़ी सी।

विशेष रूप से, सदस्य फ़ंक्शन के कार्यान्वयन को एक वर्ग के रूप में कार्यान्वित करने के लिए रणनीति पैटर्न का उपयोग करें (जिसे विशेषीकृत करने की अनुमति है)।

यह तब तक अनुमति है जब तक कि रणनीति वर्ग को नेस्टेड नहीं किया जाता है (और इसलिए अनन्य टेम्पलेट प्रकार पर निर्भर नहीं है)।

उदा। (यह शायद वाक्य रचना सही नहीं है, लेकिन यह विचार स्पष्ट किया जाना चाहिए)

template <class T> 
class OuterThingThatIsNotSpecialized 
{ 
    template <class U> 
    void memberWeWantToSpecialize(const U& someObj_) 
    { 
    SpecializedStrategy<U>::doStuff(someObj_); 
    } 
}; 

template <class U> 
struct SpecializedStrategy; 

template <> 
SpecializedStrategy<int> 
{ 
    void doStuff(const int&) 
    { 
    // int impl 
    } 
}; 

template <> 
SpecializedStrategy<SomeOtherType> 
{ 
    void doStuff(const SomeOtherType&) 
    { 
    // SOT impl 
    } 
}; 

यह अविश्वसनीय रूप से उपयोगी है क्योंकि प्रकार के लिए OuterThingThatIsNotSpecialized के लिए कॉल जहां कोई कार्यान्वयन मौजूद है बस असफल हो जायेगी संकलित करने के लिए है।

पीएस। आप इस रणनीति का आंशिक रूप से टेम्पलेट कार्यों को विशेषज्ञ बनाने के लिए भी उपयोग कर सकते हैं, जो कि अन्यथा सी ++ असंभवता है।

+0

ध्यान दें कि उसके पास सदस्य टेम्पलेट क्लास है, न कि सदस्य टेम्पलेट फ़ंक्शन। एक सदस्य टेम्पलेट वर्ग के लिए बात अधिक जटिल है। क्योंकि उदाहरण के लिए दोस्ती अब और नहीं दी गई है। –

11

1 99 8 के मानक (आईएसओ 14882: 1 99 8) की धारा 18, धारा 14.7.3 का कहना है कि (बाहरी) टेम्पलेट वर्ग वर्ग स्पष्ट रूप से विशिष्ट नहीं होने पर (आंतरिक) टेम्पलेट सदस्य वर्गों की स्पष्ट विशेषज्ञता की अनुमति नहीं है।

0

जैसा कि पिछले पोस्टर समझाया गया है, यह संभव नहीं है। हालांकि, आपको एक गैर टेम्पलेट आधार वर्ग में नेस्टेड टेम्पलेट स्थानांतरित कर सकते हैं:

struct FooBase 
{ 
    template<int b> struct Bar; 
} 
template<int a> struct Foo : public FooBase 
{ 
}; 

struct FooBase::Bar<1> // specializing Bar 
{ 
}; 
0

के रूप में अन्य लोगों ने बताया है, सी ++ नहीं करता है आप एक नेस्टेड वर्ग विशेषज्ञ अगर बाहरी वर्ग टेम्पलेट भी विशेष नहीं है।जब मैं उस तरह एक स्थिति थी, मैं एक सहायक वर्ग एक आंतरिक नाम स्थान में रखा के साथ उसके चारों ओर काम करने में सक्षम था:

namespace internal { 
    template <int a, int b> struct FooBarHelper 
    { /* ... */ }; 
    // Specialization 
    template <int a> struct FooBarHelper<a, 1> 
    { /* specialized version goes here */ }; 
} 

template<int a> struct Foo 
{ 
    template<int b> struct Bar : public internal::FooBarHelper<a, b>; 
}; 

बेशक यह नहीं है काफी छुपा के रूप में के रूप में आप इसे होना चाहते हो सकता है।

1

यहाँ मैं क्या कर रहा हूँ, जो मुझे लगता है कि आप क्या करने की कोशिश कर रहे हैं क्या साथ सरल/अधिक इनलाइन है:

हेल्पर

template<int a> struct Foo 
{ 
    template<int, int> struct Bar__; 
    template<int b> using Bar = Bar__<b, b>; 
}; 

template<int a> template<int b, int c> struct Foo<a>::Bar__ 
{ 
    // general case 
    const static int x = 0; 
}; 
template<int a> template<int b> struct Foo<a>::Bar__<b, 1> 
{ 
    const static int x = 1; 
}; 

int main(int argc, const char * argv[]) 
{ 
    std::cout << Foo<1>::Bar<0>::x << "\r\n"; // general case - output 0 
    std::cout << Foo<1>::Bar<1>::x << "\r\n"; // specialized case - output 1 
    return 0; 
} 

या के साथ - सहायक यदि आप हर बार विशेषज्ञता को दोगुना करने पर ध्यान नहीं देते हैं तो

बिना हेल्पर

template<int a> struct Foo 
{ 
    template<int b, int c> struct Bar; 
}; 

template<int a> template<int b, int c> struct Foo<a>::Bar 
{ 
    // general case 
    const static int x = 0; 
}; 
template<int a> template<int b> struct Foo<a>::Bar<b, 1> 
{ 
    const static int x = 1; 
}; 

int main(int argc, const char * argv[]) 
{ 
    std::cout << Foo<1>::Bar<0, 0>::x << "\r\n"; // general case - output 0 
    std::cout << Foo<1>::Bar<1, 1>::x << "\r\n"; // specialized case - output 1 
    return 0; 
} 
संबंधित मुद्दे