2010-03-23 8 views
5

मेरे पास vertex.h में Vertex टेम्पलेट है।यह "घोषणाकर्ता अमान्य" क्या बनाता है? सी ++

20 template<class edgeDecor, class vertexDecor, bool dir> 
21 class Vertex; 

जो मैं अपने ग्राफ़ टेम्प्लेट में उसका उपयोग: मेरे graph.h से।

मैंने वर्टेक्स टेम्पलेट का सफलतापूर्वक अपने ग्राफ, रिटर्न पॉइंटर्स को वर्टिसेस आदि में उपयोग किया है। अब पहली बार मैं एक वर्टेक्स ऑब्जेक्ट घोषित करने और उसे चालू करने की कोशिश कर रहा हूं, और जीसीसी मुझे बता रहा है कि मेरा 'घोषणाकर्ता' है 'अमान्य'। यह कैसे हो सकता है?

81 template<class edgeDecor, class vertexDecor, bool dir> 
82 Graph<edgeDecor,int,dir> Graph<edgeDecor,vertexDecor,dir>::Dijkstra(vertex s, bool print = false) const 
83 { 
84 /* Construct new Graph with apropriate decorators */ 
85 Graph<edgeDecor,int,dir> span = new Graph<edgeDecor,int,dir>(); 
86 span.E.reserve(this->E.size()); 
87 
88 typename Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX); 
89 span.V = new vector<Vertex<edgeDecor,int,dir> >(this->V.size,v); 
90 }; 

और जीसीसी कह रहा है:

graph.h: In member function ‘Graph<edgeDecor, int, dir> Graph<edgeDecor, vertexDecor, dir>::Dijkstra(Vertex<edgeDecor, vertexDecor, dir>, bool) const’: 
graph.h:88: error: invalid declarator before ‘v’ 
graph.h:89: error: ‘v’ was not declared in this scope 

मैं जानता हूँ कि यह शायद एक और noob सवाल है, लेकिन मैं किसी भी मदद की सराहना करते हैं जाएगा।

+0

शायद इस समस्या से संबंधित नहीं है, लेकिन क्या आप वाकई चाहते हैं कि "= नया Vertex (INT_MAX)"? क्या आप शायद "vertex" uncapitalised मतलब था (जो मुझे लगता है कि एक typedef है)? वर्टेक्स <...> में वास्तव में एक सीटीओआर वर्टेक्स/वर्टेक्स पॉइंटर ले रहा है? –

उत्तर

1

इगोर सही है। निम्न त्रुटि के लिए के रूप में:

Vertex<edgeDecor,int,dir> v = new Vertex<edgeDecor,int,dir>(INT_MAX); 
+0

जिसने इसे हल किया। धन्यवाद। –

4

शायद क्योंकि आप Vertex का एक उदाहरण की घोषणा कर रहे हैं

Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX); 

की जरूरत है। typename कीवर्ड केवल टेम्पलेट पैरामीटर सूची के अंदर मान्य है।

धन्यवाद अभय और टेम्पलेट पैरामीटर सूची के बाहर keyword के वैध का उपयोग करता है ओर इशारा करते हुए के लिए outis।

कोड पर फिर से विचार करने के बाद अन्य बातों के एक नंबर दिमाग में आते हैं:

  1. रूप माइक Dinsdale से कहा आप यहाँ टेम्पलेट पैरामीटर मौजूद नहीं हैं: new Vertex(INT_MAX);। इसके बजाय Vertex<edgeDecor,int,dir> आज़माएं।
  2. आप क्लास इंस्टेंस में पॉइंटर असाइन कर रहे हैं। यदि आप इसे ढेर पर बना रहे हैं तो यह कुछ ऐसा होना चाहिए:

    Vertex v (INT_MAX);

तो ढेर v पर बनाने सूचक प्रकार होना चाहिए:

Vertex<edgeDecor,int,dir>* v = new Vertex<edgeDecor,int,dir>(INT_MAX); 
+2

"टाइपनाम कीवर्ड केवल टेम्पलेट पैरामीटर सूची के अंदर मान्य है", मुझे ऐसा नहीं लगता है। टेम्पलेट-निर्भर नामों के लिए, अधिकांश कंपाइलरों को आपको * टाइपनाम * निर्दिष्ट करने की आवश्यकता होती है। – Abhay

+0

आरई निर्भर नाम: http://pages.cs.wisc.edu/~driscoll/typename.html पढ़ें। ओपी के मामले में, 'Vertex 'एक निर्भर टाइपनाम नहीं है, इसलिए' टाइपनाम 'मान्य नहीं है। – outis

+0

"टाइपनाम" कीवर्ड जीसीसी के बिना: ग्राफ.h: 88: त्रुटि: 'Vertex' से पहले अपेक्षित प्रकार-विनिर्देशक जो मुझे लगता है कि "टाइपनाम" की आवश्यकता है जो संकलक को इंगित करने के लिए यहां आवश्यक है एक प्रकार के लिए। –

0

के रूप में कहा, यह पहली खो typename की एक समस्या है:

graph.h:88: error: expected type-specifier before ‘Vertex’ 

... आप शायद कहने की जरूरत है।

कुछ उदाहरण:

template <class T> 
struct MyClass 
{ 
    struct Foo { static int MBar; }; 
}; 

template <> 
struct MyClass<int> { static int Foo; }; 

MyClass का उपयोग करना:

template <class T> 
void useMyClass(T t) 
{ 
    MyClass<T> c; 
} 

typename की कोई जरूरत नहीं है कोई अस्पष्टता नहीं है क्योंकि वहाँ, संकलक जानता है MyClass एक प्रकार यहाँ हो गया।

template <class T> 
void useFoo(T t) 
{ 
    typename MyClass<T>::Foo f; 
} 

हम को स्पष्ट करने के लिए क्योंकि संकलक पहले से पता नहीं है, तो Foo प्रतीक एक प्रकार, एक विधि या कोई विशेषता हो जाएगा की जरूरत है। वास्तव में, यदि T == int यह कोड गलत है क्योंकि Foostruct होने की बजाय static विशेषता का प्रतिनिधित्व करेगा!

void useFoo(int t) 
{ 
    int f = MyClass<int>::Foo; 
} 

void useFoo(float t) 
{ 
    float f = MyClass<float>::Foo::MBar; 
} 

यहाँ typename की आवश्यकता नहीं है: के बाद से संकलक टेम्पलेट पैरामीटर सूची में सभी प्रकार जानता है, यह MyClass<int> और MyClass<float> के लिए टेम्पलेट वर्ग का दृष्टांत कर सकते हैं और एक नियमित वर्ग के लिए के रूप में प्रत्येक इन्स्टेन्शियशन के अंदर से बाहर जानता है (और विशेष रूप से प्रत्येक प्रतीक क्या प्रतिनिधित्व करता है)।

template <class T> 
void useBar(T t) 
{ 
    int i = typename MyClass<T>::Foo::MBar; 
} 

एक बार फिर हम जरूरत typename क्योंकि Foo एक प्रकार है और संकलक यह पता करने के लिए की जरूरत है।

यदि आपको वास्तव में यह नहीं मिलता है, तो चिंता न करें। typename और template कीवर्ड कभी-कभी सामान्य कोड में असामान्य स्थानों में रेंगते हैं: बस संकलक त्रुटि के साथ शुरू होने की प्रतीक्षा करें, आप जल्द ही त्रुटियों को याद करेंगे और उन्हें एक विंक में सही करेंगे।

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