2015-03-16 14 views
9

के सदस्य को परिभाषित नहीं कर सकता मैं कस्टम आलसी स्ट्रिंग क्लास लिख रहा हूं।आश्रित टाइपपीफ

template <typename charT, typename traits = std::char_traits<charT>> 
class lazy_basic_string 
{ 
    class char_proxy 
    { 
     char_proxy& operator=(charT ch); 
    }; 

    char_proxy operator[](size_type i); 
} 

तब मैं इन विधियों को कक्षा घोषणा के बाहर परिभाषित करना चाहता हूं।

template <typename charT, typename traits> 
using char_proxy = typename lazy_basic_string<charT, traits>::char_proxy; 

template <typename charT, typename traits> 
char_proxy<charT, traits>& char_proxy<charT, traits>::operator=(charT ch) 
{ 
    ... 
} 

लेकिन मैं संकलन त्रुटि मिली:

cannot define member of dependent typedef char_proxy

तो मैं समझ नहीं है कि समस्या क्या यहाँ है। क्यों संकलक lazy_basic_string :: char_proxy के बजाय शॉर्टकट char_proxy का उपयोग नहीं कर सकता है?

उत्तर

4

यह मानक द्वारा विशेष रूप से अच्छी तरह से निर्दिष्ट नहीं प्रतीत होता है। ,

3 - When a member function, a member class, a member enumeration, a static data member or a member template of a class template is defined outside of the class template definition, the member definition is defined as a template definition in which the template-parameters are those of the class template. The names of the template parameters used in the definition of the member may be different from the template parameter names used in the class template definition. The template argument list following the class template name in the member definition shall name the parameters in the same order as the one used in the template parameter list of the member. [...]

इसका मतलब है, हालांकि नहीं वास्तव में राज्य करता है कि एक बाहर के लाइन वर्ग टेम्पलेट सदस्य परिभाषा के द्वारा वर्ग टेम्पलेट का संदर्भ लेना चाहिए: निकटतम मैं पाने के लिए दिखाई दे सकता है [temp.class] है इसका नाम, और उपनाम टेम्पलेट के माध्यम से नहीं।

यह देखना आवश्यक है कि यह आवश्यक क्यों है;

template<class T> struct S { void f(); }; 
template<class T> using s_t = std::conditional_t<sizeof(T) % 8 == 0, 
    S<T>, S<T*>>; 
template<class T> void s_t<T>::f() {} 

int main() { S<int> s; s.f(); } // defined? 
: के रूप में एक उपनाम टेम्पलेट एक मनमाने ढंग से जटिल गणना में परिणाम कर सकते हैं, ताकि एक संभावित परिभाषा के खिलाफ एक वर्ग टेम्पलेट सदस्य के उपयोग से मिलान करने में संकलक उर्फ ​​टेम्प्लेट पैरामीटर के हर संभव संयोजन पर कि गणना प्रदर्शन करने के लिए होता है

दिलचस्प बात यह है बजना (3.7) एक वर्ग टेम्पलेट सदस्य परिभाषा एक उपनाम टेम्पलेट के उपयोग की अनुमति देता है, लेकिन केवल जहां यह एक सीधी पहचान गणना है:

template<class> struct T { void f(); }; 
template<class C> using id_t = C; 
template<class C> using t_t = T<id_t<C>>; 
template<class C> void t_t<C>::f() {} // OK?? 
1

क्या संकलक आप उपयोग कर रहे हैं? यदि आप पसंद करते

template <typename charT, typename traits> 
char_proxy<charT, traits>& lazy_basic_string<charT, traits>::char_proxy::operator=(charT ch) 
{ 
    return {}; 
} 

या,: जीसीसी 4.8 के साथ, मैं यह संकलन करने के लिए कोई रास्ता नहीं मिला है, लेकिन दृश्य स्टूडियो 2015 को पूर्वावलोकन, अगर आप थोड़ा अपने कोड को संशोधित, इसे सफलतापूर्वक संकलित

template <typename charT, typename traits> 
typename lazy_basic_string<charT, traits>::char_proxy& char_proxy<charT, traits>::operator=(charT ch) 
{ 
    return{}; 
} 

जैसा कि आपने देखा होगा, मैं केवल उपनाम का उपयोग रिटर्न प्रकार के रूप में या ऑपरेटर नाम तक पहुंचने के लिए कर सकता हूं, लेकिन दोनों नहीं।

मुझे लगता है कि आपको मानक में कुछ प्रकार का अंधेरा क्षेत्र मिला है, क्योंकि निम्नलिखित कोड में वीएस और जीसीसी पर भी विभिन्न व्यवहार हैं। यह वी.एस. 2015 को है, लेकिन जीसीसी में नहीं संकलित:

template<typename T> 
class A { 
    class B { 
     B& test(); 
    }; 
}; 

template<typename T> 
using B_alias = typename A<T>::B; 

template<typename T> 
B_alias<T>& B_alias<T>::test() 
{ 
    return{}; 
} 

इस मामले में, वी.एस. पर मैं दोनों समारोह नाम का उपयोग करने के लिए और वापसी प्रकार निर्दिष्ट करने के लिए अन्य नाम का उपयोग करने में सक्षम था।

+0

मैं g ++ 4.7 का उपयोग कर रहा हूं। ऐसा लगता है कि क्लास सदस्यों की परिभाषा टेम्पलेट उपनाम द्वारा समर्थित नहीं है, इसलिए इस सुविधा से बचने के लिए बेहतर होगा। – eucpp

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