2015-02-02 4 views
5

एक वर्ग टेम्पलेट और के रूप में परिभाषित सहायक enum वर्गों पर विचार के क्रमपरिवर्तन की स्वतंत्र है इस प्रकार है:कक्षा टेम्पलेट है, जो अपने तर्कों

enum class Color {Red, Green, Blue} 
enum class ShowAxes {False, True} 
enum class ShowLabels {False, True} 

template< Color, ShowAxes, ShowLabels > 
class A 
{......}; 

सवाल है, कैसे वर्ग एक फिर से परिभाषित करने, जिस पर स्वतंत्र होगा इसके तर्कों के क्रमपरिवर्तन। मैं देव सी ++ का उपयोग करता हूं, जो सी ++ 11 का समर्थन करता है।

[संपादित करें]

उदाहरण के लिए, एक के नए संस्करण

A< Color::Red, ShowAxes::True, ShowLabels::True > 
A< Color::Red, ShowLabels::True, ShowAxes::True > 
A< ShowAxes::True, Color::Red, ShowLabels::True > 
A< ShowLabels::True, Color::Red, ShowAxes::True > 
A< ShowLabels::True, Color::Red, ShowAxes::True > 
A< ShowAxes::True, Color::Red, ShowLabels::True > 

संस्करणों का समर्थन करना चाहिए, और उन सभी को समान हैं, यानी वे एक ही कक्षा उत्पन्न करते हैं।

+0

C++ वर्ग टेम्पलेट विशेषज्ञता? –

+1

@ ब्रायन चेन आप विशेषज्ञता के साथ पैरामीटर के प्रकार नहीं बदल सकते –

+0

मैं पैरामीटर के प्रकारों को बदलना नहीं चाहता हूं। विशेषज्ञता एक अच्छा विचार है, लेकिन मेरे पास 3 है! = 6 क्रमपरिवर्तन। इसके अलावा, मैं और पैरामीटर जोड़ने जा रहा हूँ। –

उत्तर

5

गैर-प्रकार पैरामीटर का उपयोग करके आपके वर्तमान इंटरफ़ेस के साथ यह संभव नहीं है।

आप के बजाय प्रकार पैरामीटर ले जा सकते हैं और एक std::integral_constant में मानों लपेट:

template<class X, class Y, class Z> 
class A { /* stuff */ }; 

// use as: 
A<std::integral_constant<Color, Color::Red>, 
    std::integral_constant<ShowAxes, ShowAxes::True>, 
    std::integral_constant<ShowLabels, ShowLabels::True>> a; 

इस बल्कि वर्बोज़ है, तो आप एक मैक्रो लिखने पर विचार कर सकता है:

#define AS_IC(Value) std::integral_constant<decltype(Value), Value> 

और

के रूप में फिर से लिखने
A<AS_IC(Color::Red), AS_IC(ShowAxes::True), AS_IC(ShowLabels::True)> a; 

वांछित प्रकार के मूल्य को 0 की सूची से निकालनारों सीधा है:

template<class Result, class...> 
struct extract; 

template<class Result, Result Value, class... Tail> 
struct extract<Result, std::integral_constant<Result, Value>, Tail...> : std::integral_constant<Result, Value> {}; 

template<class Result, class Head, class... Tail> 
struct extract<Result, Head, Tail...> : extract<Result, Tail...> {}; 

तो फिर तुम

// inside the definition of A 
static constexpr Color col = extract<Color, X, Y, Z>::value; 

Demo कर सकते हैं।

यह नहीं है, तथापि, एक ही कक्षा उत्पन्न है, लेकिन आप एक वर्ग टेम्पलेट A_impl कि गैर प्रकार पैरामीटर के साथ अपने A की तरह बर्ताव कर सकते हैं, और कहा कि वास्तविक क्रियान्वयन में शामिल है, और फिर A एक उपनाम टेम्पलेट बनाने:

template< Color, ShowAxes, ShowLabels > 
class A_impl 
{/* stuff */}; 

template<class X, class Y, class Z> 
using A = A_impl<extract<Color, X, Y, Z>::value, 
       extract<ShowAxes, X, Y, Z>::value, 
       extract<ShowLabels, X, Y, Z>::value>; 

अब दिया

A<AS_IC(Color::Red), AS_IC(ShowAxes::True), AS_IC(ShowLabels::True)> a; 
A<AS_IC(Color::Red), AS_IC(ShowLabels::True), AS_IC(ShowAxes::True)> b; 

a और b एक ही प्रकार की है। Demo

विकल्प में, आप भी decltype और अधिक भार समारोह टेम्पलेट का उपयोग कर सकते हैं, लेकिन उस प्रकार के हर संभव आदेश के लिए एक समारोह टेम्पलेट घोषणा जोड़ने की आवश्यकता है:

template< Color c, ShowAxes a, ShowLabels l> 
A<c,a,l> A_of(); 

template< ShowAxes a, ShowLabels l, Color c> 
A<c,a,l> A_of(); 

// etc. 

decltype(A_of<Color::Red, ShowAxes::True, ShowLabels::True>()) a1; 
decltype(A_of<ShowAxes::True, ShowLabels::True, Color::Red>()) a2; 
+0

'std :: integral_constant' और' निकालने 'का विचार अच्छा लग रहा है। मैं कोड के अनुकूलन के बारे में सोचूंगा। –

+0

मेरे पास एक छोटा (शायद मामूली) प्रश्न है। एक गैर-निर्देशक कर्मचारियों द्वारा मैक्रो AS_IC को प्रतिस्थापित करना संभव है, क्लास टेम्पलेट या टेम्पलेट फ़ंक्शन कहें? –

+1

@VahagnPoghosyan कोई मैक्रो-फ्री तरीका नहीं है जब आप 'ए' घोषित करते समय बहुत सारे बॉयलरप्लेट को जोड़ने के बारे में जानते हैं। –

0

शायद std::is_same का उपयोग कर। तो फिर आप अपने कोड इस तरह से आसान बनाने में कर सकते हैं:

template <typename A, typename B, typename C> 
class X 
{ 
public: 
    X() { 
     static_assert(
      std::is_same<A, Color>::value || 
      std::is_same<B, Color>::value || 
      std::is_same<C, Color>::value, 
      "nope"); 
     // other assertions here! 
     // also, make sure your types are different ;) 
    } 
    X(A a, B b, C c) : X() { 
     // your code here 
    } 
}; 

template <typename A, typename B, typename C> 
X<A, B, C> make(A a, B b, C c) { 
    // possible verifications here 
    return X<A, B, C>(a, b, c); 
} 

int main() { 
    auto a = make(Color::Red, ShowAxes::true, ShowLabels::True); 
    return 0; 
} 

आप अपने प्रकार के सभी सत्यापित कर सकते हैं ए, बी & सी

मैं माफी चाहता हूँ, लेकिन मैं किसी भी अन्य समाधान नहीं दिख रहा। :/

+2

ओपी का कोड गैर-प्रकार के टेम्पलेट पैरामीटर की अपेक्षा करता है –

+0

मैंने अपने लक्ष्य के विस्तृत स्पष्टीकरण के लिए प्रश्न में कुछ पाठ जोड़ा। –

+0

मैंने अपनी पोस्ट संपादित की। – vincentp

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