2013-01-08 11 views
11

मैं एक छोटा सा पुस्तकालय है कि सी ++ 11 metaprogramming तकनीकों और CRTP का एक बहुत का उपयोग लिखा है संकलित करने के लिए असफल हो, और यह जी ++ 4.7.2बजना और इंटेल इस CRTP कोड

अब साथ अच्छी तरह से संकलित, मैं करने की कोशिश इसे इंटेल आईसीपीसी 13.0.0.079 के साथ संकलित करें और यह कई सैकड़ों त्रुटियों को उत्पन्न करता है। तो मैं एक के बाद समस्याओं को अलग करने की कोशिश करता हूं।

test_crtp.cpp(26): error: type "Derived<Type>::Derived" is not a class template 
     Derived(): Base<Derived, Type>() {;} 
        ^

test_crtp.cpp(26): error: "Base" is not a nonstatic data member or base class of class "Derived<int>" 
     Derived(): Base<Derived, Type>() {;} 
       ^
      detected during instantiation of "Derived<Type>::Derived() [with Type=int]" at line 31 

compilation aborted for test_crtp.cpp (code 2) 

तो यह एक है:

तो, पहले, इस कोड, कि जी ++ 4.7.2

#include <iostream> 

template<template<typename> class Crtp, typename Type> 
struct Base {}; 

template<typename Type> 
struct Derived : public Base<Derived, Type> 
{ 
    Derived(): Base<Derived, Type>() {;} 
}; 

int main() 
{ 
    Derived<int> x; 
    return 0; 
} 

दोनों icpc और बजना के तहत कोई समस्या नहीं के साथ संकलित असफल इस कोड को संकलित करने के लिए पर विचार इंटेल और क्लैंग में बग, या जी ++ में? यदि यह इंटेल और क्लैंग में है, तो क्या आपको लगता है कि इसे भविष्य के संस्करण में हल किया जाएगा?

+0

यह एक अच्छा सवाल है, लेकिन आमतौर पर सीआरटीपी टेम्पलेट-टेम्पलेट पैरामीटर से परेशान नहीं होता है, लेकिन केवल व्युत्पन्न वर्ग प्रकार को पास करता है। 'टेम्पलेट <टाइपनाम नामित> संरचना आधार; टेम्पलेट संरचना व्युत्पन्न: बेस < Derived> {...}; 'अधिक सामान्य है। –

+0

... यदि आप 'टाइप' का प्रचार करना चाहते हैं, तो हो सकता है कि आप 'व्युत्पन्न' में 'टाइपपीफ' हो सकें जो इसे उजागर करता है ... – Nim

+1

पहचानकर्ता 'व्युत्पन्न' नाम, अपनी कक्षा के भीतर, पूर्ण प्रकार 'व्युत्पन्न '।इसे * इंजेक्शन * क्लास नाम कहा जाता है। मुझे लगता है कि यह जीसीसी के साथ एक बग है। – Xeo

उत्तर

7

कक्षा Derived के अंदर, नाम Derived नाम (तत्काल) वर्ग, वर्ग टेम्पलेट नहीं है। इसके बजाय Base< ::Derived, Type> आज़माएं (< और: :) के बीच एक जगह छोड़ने के लिए सावधान रहें।

+4

नोट: अंतरिक्ष का कारण यह है कि '<:' को [digraph] (http://en.wikipedia.org/wiki/Digraphs_and_trigraphs) के रूप में व्याख्या किया जा सकता है, और इस प्रकार '<::' ' [: 'preprocessing के बाद ... –

+5

सी ++ 11 में, आप केवल' <:: व्युत्पन्न 'लिख सकते हैं,' <: 'को टेम्पलेट तर्क सूची में एक digraph के रूप में व्याख्या नहीं किया गया है। – Xeo

+1

@MatthieuM। यह भी ध्यान रखें कि सी ++ 11 (या जीसीसी <4.8) = –

6

सेक्शन 9.2.3 में सी ++ टेम्पलेट पूर्ण गाइड (Amazon), इंजेक्शन क्लास नाम पर एक चर्चा है। उद्धरण के लिए:

कक्षा टेम्पलेट्स ने कक्षा के नाम इंजेक्शन दिए हैं। हालांकि, वे सामान्य इंजेक्शन वाले वर्ग नामों से अजनबी हैं: उनके बाद टेम्पलेट तर्क (जिसके मामले में उन्हें कक्षा टेम्पलेट नाम इंजेक्शन दिया जाता है), लेकिन यदि वे टेम्पलेट तर्कों का पालन नहीं करते हैं तो वे कक्षा के साथ इसका प्रतिनिधित्व करते हैं पैरामीटर इसके तर्क के रूप में (या, आंशिक विशेषज्ञता के लिए, इसके विशेषज्ञता तर्क)। इससे पता चलता है निम्नलिखित स्थिति:

template<template<typename> class TT> 
class X {}; 

template<typename T> 
class C 
{ 
    Ca;  // OK: same as ''C<T> a;'' 
    C<void> b; // OK 
    X<C> c; // ERROR: C without a template argument list 
       // does not denote a template 
    X<::C> d; // ERROR: <: is an alternative token for [ 
    X< ::C> e; // OK: the space between < and :: is required 
} 

नोट कैसे अयोग्य नाम इंजेक्शन नाम का उल्लेख और अगर यह टेम्पलेट तर्कों की सूची के बाद नहीं है टेम्पलेट के नाम पर विचार नहीं किया है । क्षतिपूर्ति करने के लिए, हम फ़ाइल स्कोप क्वालीफायर :: का उपयोग करके टेम्पलेट के नाम को बल दे सकते हैं। यह काम करता है, लेकिन हमें सावधान रहना चाहिए कि एक तथाकथित डिग्राफ टोकन <: जिसे बाएं ब्रैकेट के रूप में व्याख्या किया गया है, को बनाने के लिए सावधान रहना चाहिए। हालांकि अपेक्षाकृत दुर्लभ, ऐसी त्रुटियों के परिणामस्वरूप परेशान निदान में परिणाम होता है।

तो क्या अपने कोड में होता है कि Base<Derived, Type>Base<Derived<Type>, Type> जो बीमार बनाई है के रूप में व्याख्या की जा रही है। इसलिए आपको डिग्राफ से बचने के लिए < के बीच की जगह के साथ स्कोप क्वालीफायर :: का उपयोग करने की आवश्यकता है।

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