2013-08-11 13 views
5

मैं निम्नलिखित कोड नहीं है:गैर प्रकार टेम्पलेट तर्क एक निरंतर अभिव्यक्ति

#include <cstdlib> 
#include <cstdio> 
#include <atomic> 

enum ATYPE { Undefined = 0, typeA, typeB, typeC }; 

template<ATYPE TYPE = Undefined> 
struct Object 
{ 
    Object() { counter++; } 
    static std::atomic<int> counter; 
}; 

template<ATYPE TYPE> 
std::atomic<int> Object<TYPE>::counter(1); 

template<ATYPE TYPE> 
void test() 
{ 
    printf("in test\n"); 
    Object<TYPE> o; 
} 

int main(int argc, char **argv) 
{ 
    test<typeA>(); 
    printf("%d\n", Object<typeA>::counter.load()); 
    Object<typeA>::counter.store(0); 
    for (int i = 0; i < sizeof(ATYPE); ++i) { 
     Object<static_cast<ATYPE>(i)>::counter.store(0); 
    } 
    return 0; 
} 

जब मैं निम्न आदेश लाइन के साथ संकलन:

clang++ -o test -std=c++11 -stdlib=libc++ test.cpp 

मैं निम्नलिखित त्रुटियाँ मिलती है:

test.cpp:32:20: error: non-type template argument is not a constant expression 
Object<static_cast<ATYPE>(i)>::counter.store(0); 
^~~~~~~~~~~~~~~~~~~~~ 
test.cpp:32:39: note: read of non-const variable 'i' is not allowed in a constant expression 
Object<static_cast<ATYPE>(i)>::counter.store(0); 
^ 
testray.cpp:31:18: note: declared here 
for (int i = 0; i < sizeof(ATYPE); ++i) { 

मुझे विश्वास है कि मैं समझता हूं। टेम्पलेट का तर्क एक constexpr होना चाहिए और मैं स्पष्ट रूप से नहीं है। तो सवाल यह है कि, क्या वे इस काम को पाने के लिए संभव परिवर्तन कर सकते हैं। इस काम करके, मेरा मतलब है, मैं किसी भी तरह ATYPE में प्रत्येक प्रकार के लिए इस टेम्पलेट वर्ग से इन स्थिर काउंटर रीसेट करने का कोई बेहतर तरीका अन्य बस इसे मैन्युअल रूप से कर रही है की तुलना में हो सकता है,:

Object<Undefined>::counter.store(0); 
Object<typeA>::counter.store(0); 
... 

कौन इतना सुंदर और व्यावहारिक नहीं है जब ATYPE में कई प्रकार होते हैं।

आपकी मदद और सलाह के लिए बहुत बहुत धन्यवाद।

+1

आप वैसे भी अपने enum गलत के माध्यम से लूप कर रहे हैं। त्रुटि संदेश के रूप में या तो निरंतर अभिव्यक्ति नहीं है। – Rapptz

+0

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

+0

क्या रैपिट्ज़ का मतलब है कि मैं गतिशील हूं और संकलन समय टेम्पलेट तर्क –

उत्तर

7

बातें इस तरह के लिए, प्रत्यावर्तन आम तौर पर एक सरल उपाय है:

#include <type_traits> 

enum ATYPE { Undefined = 0, typeA, typeB, typeC, ATYPE_END }; 

void reset_Object_counter(std::integral_constant<ATYPE, ATYPE_END>) 
{} 

template < ATYPE n = Undefined > 
void reset_Object_counter(std::integral_constant<ATYPE, n> p = {}) 
{ 
    Object<p>::counter.store(0); 
    reset_Object_counter(std::integral_constant<ATYPE, 
               static_cast<ATYPE>(n+1)>{}); 
} 

इस मामले के लिए, AFAIK, समारोह टेम्पलेट विशेषज्ञता के रूप में अच्छी तरह से (प्रथम अधिभार के बजाय) काम करता है:

template<> 
void reset_Object_counter<ENUM_END>(std::integral_constant<ATYPE, ENUM_END>) 
{} 

किसी भी तरह से, उपयोग सभी Object<...> के काउंटर 0 पर सेट करने के लिए है।


integral_constant समाधान overkill यहाँ (क्योंकि समारोह टेम्पलेट विशेषज्ञता अधिभार प्रत्यावर्तन समाप्त होने की जगह ले सकता है) थोड़ा वास्तव में है, इस समस्या के लिए एक गैर प्रकार टेम्पलेट पैरामीटर पर्याप्त है।

template < ATYPE n = Undefined > 
void reset_Object_counter() 
{ 
    Object<n>::counter.store(0); 
    reset_Object_counter<static_cast<ATYPE>(n+1)>(); 
} 
template<> 
void reset_Object_counter<ENUM_END>() 
{} 
+0

शानदार। यही वह जगह है जहां मुझे एहसास हुआ कि मुझे सी ++ पर्याप्त नहीं पता है। मैंने कभी भी integral_constant के बारे में नहीं सुना है ... लेकिन मैं उन सभी नई चीजों पर ध्यान दे रहा हूं जो हम सी ++ 11 में पा सकते हैं और ऐसा लगता है कि यह जीवनभर ले सकता है। धन्यवाद बहुत अच्छा जवाब, और सभी को thx। – user18490

+0

@ user18490 'integral_constant' यहां भी आवश्यक नहीं है;) – dyp

+0

हाँ मैं वास्तव में बिना कोड लिखने की कोशिश कर रहा हूं, क्योंकि मैंने अनुमान लगाया है कि यह बिना काम कर सकता है, लेकिन मुझे कुछ सीखने में खुशी हुई। इस अतिरिक्त टिप्पणी के लिए धन्यवाद। दूसरा समाधान जोड़ने के लिए – user18490

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

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