2009-10-04 19 views
5

मेरे पास इस तरह का एक टेम्प्लेट क्लास है:टेम्पलेट में const_cast। क्या कोई असंगत संशोधक है?

template<T> 
class MyClass 
{ 
    T* data; 
} 

कभी-कभी, मैं निम्न प्रकार के निरंतर प्रकार टी के साथ कक्षा का उपयोग करना चाहता हूं:

MyClass<const MyObject> mci; 

लेकिन मैं const_cast<MyObject*>data का उपयोग कर डेटा को संशोधित करना चाहता हूं (यह यह महत्वपूर्ण नहीं है कि क्यों MyClass एक संदर्भ गणना स्मार्ट पॉइंटर क्लास है जो संदर्भ डेटा को संदर्भ में रखता है। MyObject कुछ प्रकार से प्राप्त होता है जिसमें गिनती होती है। डेटा को संशोधित नहीं किया जाना चाहिए, लेकिन गिनती स्मार्ट द्वारा संशोधित की जानी चाहिए सूचक।)।

T से कॉन्स्ट-नेस को निकालने का कोई तरीका है? काल्पनिक कोड:

const_cast<unconst T>(data) 

?

उत्तर

11

यहां संदर्भ का सबसे आसान तरीका संदर्भ गणना को व्यवहार्य बनाना होगा।

हालांकि, अगर आप यह कैसे const_cast साथ काम करेंगे में रुचि रखते हैं, तो reimplementing बढ़ावा के remove_const काफी सरल होना चाहिए:

template <class T> 
struct RemoveConst 
{ 
    typedef T type; 
}; 

template <class T> 
struct RemoveConst<const T> 
{ 
    typedef T type; 
}; 

const_cast<typename RemoveConst<T>::type*>(t)->inc(); 
+0

यह समझाने के लिए धन्यवाद कि remove_const मेरे लिए कैसे काम करता है। – danatel

+3

@ डानाटेल: आप वास्तव में remove_const का उपयोग नहीं करना चाहते हैं।दूरसंचार को कास्ट करके एक कॉन्स वैल्यू को संशोधित करना अनिर्धारित व्यवहार है। आप refcount चर पर __mutable__ का उपयोग करना चाहते हैं। –

+0

:-) मैं म्यूटेबल का उपयोग करता हूं। मैं अपने समस्या का समाधान की जरूरत नहीं किया, समस्या नहीं थी सिर्फ एक उदाहरण के रूप में (कृपया मूल पोस्ट पढ़ें) - मैं उत्सुक था अगर वहाँ constantness दूर करने के लिए एक तरीका है। – danatel

5

आपके पास उत्तर है। const_cast दोनों दिशाओं में काम करता है:

char* a; 
const char* b; 

a = const_cast<char*>(b); 
b = const_cast<const char*>(a); // not strictly necessarily, just here for illustration 

आपके लिए विशिष्ट समस्या के रूप में, क्या आपने म्यूटेबल कीवर्ड माना है? यह एक सदस्य चर को एक कॉन्स्ट विधि के अंदर संशोधित करने की अनुमति देता है।

class foo { 
    mutable int x; 
public: 
    inc_when_const() const { ++x; } 
    dec_when_const() const { --x; } 
}; 
+0

लेकिन यह एक टेम्पलेट वर्ग है। टी कुछ है। सवाल यह है कि मैं टी से कुछ नॉनकॉन्स्ट कैसे बना सकता हूं? – danatel

+1

+1 उत्परिवर्तनीय उत्तर यहां है। – UncleBens

3

आप बूस्ट का उपयोग कर सकते हैं, प्रकार लक्षण पुस्तकालय remove_const metafunction करता है कि प्रदान करता है।

+0

दुर्भाग्य से, इस परियोजना पर मैं बूस्ट का उपयोग नहीं कर सकता। लेकिन अगर मानक सी ++ में ऐसा करने का कोई आसान तरीका रहा तो कोई भी remove_const लिख नहीं पाएगा। इसलिए ऐसा कोई रास्ता नहीं है। – danatel

+0

क्या आपने अन्य उत्तरों को पढ़ा? बूस्ट सिर्फ मेटा-टेम्पलेटेड संस्करण है, बस const_cast का उपयोग करें और उसमें से कॉन्स्ट को हटा दें या mutable, जैसे jumcchellio ने कहा। – GManNickG

4

अपने घुसपैठ सूचक द्वारा प्रबंधित कक्षा में संदर्भ गणना को परिवर्तनीय बनाएं। यह पूरी तरह से उचित है, और "तार्किक स्थिरता" को बिल्कुल सही ढंग से प्रतिबिंबित करता है - यानी ऑब्जेक्ट की संदर्भ गणना को बदलना वस्तु की स्थिति में किसी भी बदलाव को प्रतिबिंबित नहीं करता है। दूसरे शब्दों में, संदर्भ गणना वस्तु का तर्कसंगत हिस्सा नहीं है - ऑब्जेक्ट केवल इस अर्ध-असंबंधित डेटा को स्टोर करने के लिए एक सुविधाजनक स्थान होता है।

0

यहाँ मेरी सी ++ 11 unconst समारोह template है।

यदि आप इसका उपयोग करते हैं, तो आप undefined behavior के साथ छेड़छाड़ कर रहे हैं। आप चेतावनी दी गई हैं।

// on Ubuntu (and probably others) compile and test with               
// g++ -std=c++11 test.c && ./a.out ; echo $?        

template < class T > T & unconst (T const & t) { 
    return const_cast < T & > (t) ; 
} 

// demonstration of use 

struct { 
    const int n = 4; 
} s; 

int main() { 
    unconst (s.n) = 5; 
    return s.n; 
} 
+0

मुझे लगता है कि यह आसान होगा और इसका असर होगा: 'टेम्पलेट टी एंड अनकॉन्स्ट (टी कॉन्स्ट एंड टी) {वापसी const_cast <टी &>(t);} '। – alfC

+0

धन्यवाद! यह आसान है और काम करने लगता है। मुझे आश्चर्य हुआ कि 'टाइपनाम' और 'कक्षा' के बीच क्या अंतर था। – mpb