2014-06-12 8 views
6

मैं इस तरह, टेम्पलेट विशेषज्ञता के कुछ स्थिर सदस्यों को परिभाषित करना चाहते:सी ++ में फ़ंक्शन के बाहर 'उपयोग' कथन के दायरे को कैसे सीमित करें?

namespace A { 

{ 
    using T = A1::A2::...::MyClass1; 
    template <> int C<T>::member1_ = 5; 
    template <> int C<T>::member2_ = 5; 
    template <> int C<T>::member3_ = 5; 
} 

{ 
    using T = B1::B2::...::MyClass2; 
    template <> int C<T>::member1_ = 6; 
    template <> int C<T>::member2_ = 6; 
    template <> int C<T>::member3_ = 6; 
} 

... 

} 
:

namespace A { 

template <> int C<A1::A2::...::MyClass1>::member1_ = 5; 
template <> int C<A1::A2::...::MyClass1>::member2_ = 5; 
template <> int C<A1::A2::...::MyClass1>::member3_ = 5; 

template <> int C<B1::B2::...::MyClass2>::member1_ = 6; 
template <> int C<B1::B2::...::MyClass2>::member2_ = 6; 
template <> int C<B1::B2::...::MyClass2>::member3_ = 6; 

... 

} 

लेकिन कोड को आसान बनाने (और यह अधिक संरचित बनाने) के लिए, मैं इस तरह कुछ करना चाहता हूँ

कंपाइलर एक त्रुटि देता है: expected unqualified-id। क्या "बाहरी" स्थान में using स्कोप को सीमित करने के तरीके हैं?

+1

क्या आपने सी ++ 11 मोड में संकलित किया था? – TemplateRex

+0

@TemplateRex हाँ, मैं करता हूं। –

+0

मैंने नामस्थान उपनाम का उपयोग करके एक नए दृष्टिकोण के साथ आज के अपने पहले के उत्तर को हटा दिया। – TemplateRex

उत्तर

5

आप कोड ब्लॉक (यानी {...}) बाहरी कार्यों को घोंसला नहीं कर सकते हैं।

namespace A1 { namespace A2 { 
    class MyClass1; 
}} 

namespace B1 { namespace B2 { 
    class MyClass2; 
}} 

namespace A { 
template<typename T> 
struct C 
{ 
    static int member1_; 
    static int member2_; 
    static int member3_; 
}; 
} 

आप या तो import the names into namespace A, उनमें योग्यता A:: माध्यम से उपलब्ध कराते कर सकते हैं::

मान लीजिए कि हम आम में इस भाग करते

namespace A { 
using A1::A2::MyClass1; 
template <> int C<MyClass1>::member1_ = 5; 
template <> int C<MyClass1>::member2_ = 5; 
template <> int C<MyClass1>::member3_ = 5; 

using B1::B2::MyClass2; 
template <> int C<MyClass2>::member1_ = 6; 
template <> int C<MyClass2>::member2_ = 6; 
template <> int C<MyClass2>::member3_ = 6; 
} 

लेकिन मुझे लगता है कि अवांछित है और आप यह देख प्रदूषण के रूप में। तो फिर केवल एक चीज आप कर सकते हैं :: की संख्या में कमी करने के लिए use an extra namespace है:

namespace A { 
namespace T { 
using T1 = A1::A2::MyClass1; 
using T2 = B1::B2::MyClass2; 
} 

template <> int C<T::T1>::member1_ = 5; 
template <> int C<T::T1>::member2_ = 5; 
template <> int C<T::T1>::member3_ = 5; 


template <> int C<T::T2>::member1_ = 6; 
template <> int C<T::T2>::member2_ = 6; 
template <> int C<T::T2>::member3_ = 6; 
} 

यह रहता है अपने namespace A, अवांछित typenames के स्पष्ट हालांकि यह एक "कार्यान्वयन नाम स्थान" T (जो एक के लिए एक भयानक नाम है का परिचय नाम स्थान !!!)।

एक तीसरा विकल्प specializes struct template C for the types you want:

namespace A{ 
template<> 
struct C<A1::A2::MyClass1> 
{ 
    static const int member1_ = 5; 
    static const int member2_ = 5; 
    static const int member3_ = 5; 
}; 

template<> 
struct C<B1::B2::MyClass2> 
{ 
    static const int member1_ = 5; 
    static const int member2_ = 5; 
    static const int member3_ = 5; 
}; 
} 

ध्यान दें कि यह static const डेटा सदस्यों की आवश्यकता है। तुम भी तो जैसे struct टेम्पलेट की एक घोषणा के साथ भाग कर सकते हैं:

namespace A { 
template<typename T> 
struct C; 
} 

केवल प्रकार आप चाहते हैं (संकलन समय पर) इसके उपयोग को सीमित करने के लिए। यह मुझे मेरा पसंदीदा समाधान होगा।

3

यह हल करने में एक मुश्किल समस्या है। कई बाधाएं हैं।

  • टेम्पलेट विशेषज्ञता नामस्थान स्कोप पर होती है, यह आपके स्थानीय दायरे ब्रेसिज़ { } से बाहर निकलती है।
  • एक टेम्पलेट विशेषज्ञता प्राथमिक नाम के रूप में एक ही नामस्थान में रहता है, यह स्थानीय namespace detail1 { } और namespace detail2 { }namespace A के अंदर नियम करता है। हालांकि g ++ गलत तरीके से इस समाधान को स्वीकार करता है, लेकिन क्लैंग सही ढंग से इसे अस्वीकार करता है (नोट: यह वह जगह थी जहां मैं आज पहले अटक गया था और अस्थायी रूप से इस उत्तर को हटा दिया था)।
  • using निर्देशों और घोषणाओं सभी ग्राहकों को जो इस हेडर
  • inline नामस्थान में रहने वाले टेम्पलेट्स अपने सभी संलग्न नाम स्थान के अंदर विशेष किया जा सकता है शामिल हैं, लेकिन घोषित namespace Ainline होने के लिए ही काम करता है अगर यह दोनों A और से घिरा है नामस्थान को दूषित B नेमस्पेस अनुक्रम, जो असंभव है।

साफ दृष्टिकोण नेस्टेड नामस्थान की लंबी A1::A2::...::AN और B1::B2::...::BN दृश्यों के लिए namespace aliaseslibA और libB उपयोग करने के लिए, और उनके हेडर से उन उपनाम निर्यात करने के लिए है। यह क्लाइंट कोड और वास्तविक टेम्पलेट विशेषज्ञता दोनों को सरल बनाता है।

#include <iostream> 

// file C.h 

namespace A { 

template<class T> 
struct C 
{ 
    static int member1_, member2_, member3_; 
}; 

} // namespace A 

// file A.h 

namespace A1 { namespace A2 { 

struct MyClass1 {}; 

}} // namespace A1, A2 

// export namespace alias to hide implementation details 
namespace libA = A1::A2;  

namespace A { 

template <> int C<libA::MyClass1>::member1_ = 5; 
template <> int C<libA::MyClass1>::member2_ = 5; 
template <> int C<libA::MyClass1>::member3_ = 5; 

} // namespace A 

// file B.h 

namespace B1 { namespace B2 { 

struct MyClass2 {}; 

}} // namespace B1, B2 

// export namespace alias to hide implementation details 
namespace libB = B1::B2;  

namespace A { 

template <> int C<libB::MyClass2>::member1_ = 6; 
template <> int C<libB::MyClass2>::member2_ = 6; 
template <> int C<libB::MyClass2>::member3_ = 6; 

} // namespace A 

// file main.cpp 

int main() 
{ 
    std::cout << A::C<libA::MyClass1>::member1_ << "\n"; 
    std::cout << A::C<libA::MyClass1>::member2_ << "\n"; 
    std::cout << A::C<libA::MyClass1>::member3_ << "\n"; 
    std::cout << A::C<libB::MyClass2>::member1_ << "\n"; 
    std::cout << A::C<libB::MyClass2>::member2_ << "\n"; 
    std::cout << A::C<libB::MyClass2>::member3_ << "\n";  
} 

Live Example

नोट अभी भी MyClass1 और MyClass2 की पुनरावृत्ति में बायलर थाली के एक हल्के sympton है वहाँ है, लेकिन कोड और अधिक जगह में नाम स्थान उपनाम के साथ कॉम्पैक्ट है।

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

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