2012-01-26 9 views
6

इस answer में मैंने this का उपयोग करने के लिए और decltype अभिव्यक्ति के भाग के रूप में पिछली वापसी प्रकार में _arg की विशेषता का उपयोग करने के लिए समझ में आया। बिना करना, लेकिन असुविधाजनक करना संभव है।इसका उपयोग और सदस्य फ़ंक्शन पीछे वापसी प्रकारों में विशेषताएँ?

न तो क्लैंग 3.0 (नीचे देखें) और न ही gcc 4.5.2 हालांकि इसे स्वीकार किया गया।

#include <iostream> 

class MyClass { 
public: 
    MyClass(int i): _arg(i) {} 

    template <typename F> 
    auto apply(F& f) -> decltype(f(_arg)) { 
    return f(_arg); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _arg)) { 
    return f(*this, _arg); 
    } 

private: 
    int _arg; 
}; 

struct Id { 
    template <typename V> 
    V operator()(V v) const { return v; } 
}; 

struct ComplexId { 
    template <typename C, typename V> 
    V operator()(C const&, V v) { return v + 1; } 
}; 

int main() { 
    Id id; ComplexId complex; 

    MyClass c(0); 

    std::cout << c.apply(id) << " " << c.apply(complex) << "\n"; 
} 

बजना 3.0 का कहना है:

$ clang++ -std=c++11 -Weverything test.cpp 
test.cpp:8:38: error: use of undeclared identifier '_arg' 
     auto apply(F& f) -> decltype(f(_arg)) { 
            ^
test.cpp:8:45: error: type name requires a specifier or qualifier 
     auto apply(F& f) -> decltype(f(_arg)) { 
              ^
test.cpp:8:45: error: C++ requires a type specifier for all declarations 
     auto apply(F& f) -> decltype(f(_arg)) { 
          ~~~~~~~~  ^
test.cpp:8:7: error: 'auto' return without trailing return type 
     auto apply(F& f) -> decltype(f(_arg)) { 
    ^
test.cpp:13:39: error: invalid use of 'this' outside of a nonstatic member function 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
            ^
test.cpp:13:52: error: type name requires a specifier or qualifier 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
               ^
test.cpp:13:52: error: C++ requires a type specifier for all declarations 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
          ~~~~~~~~    ^
test.cpp:13:7: error: 'auto' return without trailing return type 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
    ^
8 errors generated. 

हम ... इतना महान नहीं।

हालांकि, सी ++ 11 का समर्थन अधिकांश कंपाइलरों में सबसे अच्छा हैकी और मुझे मानक (एन 32 9 0) में निर्दिष्ट विशिष्ट प्रतिबंध नहीं मिल सका।

टिप्पणियों में, Xeo सुझाव दिया कि यह मानक में एक दोष हो सकता है ...

तो, यह अनुमति नहीं है?

बोनस: और क्लैंग/जीसीसी के अधिक हाल के संस्करणों का समर्थन करते हैं?

+0

क्लैंग 3.1 HEAD एक ही त्रुटि को हल करता है। – Xeo

+0

जीसीसी 4.7 पर इसी तरह की त्रुटियां। –

+0

बीटीडब्ल्यू, मैंने अभी पाया [यह दिलचस्प, समान प्रश्न] (http://stackoverflow.com/q/7255379/500104)। इसके अलावा, सदस्य को आगे घोषित करने के @ जोहान्स के सुझाव के साथ, मुझे क्लैंग 3.1 हेड के साथ अब '_arg' के बारे में नहीं, पीछे वापसी प्रकार में' this' के बारे में एक त्रुटि मिलती है। – Xeo

उत्तर

9

मैंने गलत समझा। यह a defect at some point था, लेकिन अंत में resolved and voted into the FDIS था।

§5.1.1 [expr.prim.general]

एक घोषणा वाणी तो एक वर्ग X के एक सदस्य समारोह या सदस्य समारोह टेम्पलेट, अभिव्यक्ति this "सीवी-क्वालीफायर-सेकX सूचक" प्रकार का एक prvalue वैकल्पिक के बीच है सीवी-qualifer-सेक और समारोह परिभाषा, सदस्य-declarator, या declarator के अंत।

इस प्रकार, क्लैंग और जीसीसी अभी तक इसे सही तरीके से लागू नहीं करते हैं।

struct X{ 
    // 'this' exists between the | markers 
    void f() const volatile | { 
    } | 
    auto g() const volatile | -> void { 
    } | 
}; 
1

यदि आप जो लिखते हैं कानूनी है मैं नहीं जानता, लेकिन वहाँ प्राप्त करने के कुछ अन्य तरीकों से आप क्या चाहते हैं:

template <typename F> 
    auto apply(F& f) -> decltype(f(*(MyClass*)0, (int)0)) { 
    return f(*this, _arg); 
    } 

या:

template <typename F> 
    typename std::result_of<F(MyClass,int)>::type apply(F& f) { 
    return f(*this, _arg); 
    } 
+0

उत्तर में मैंने जो जवाब दिया, उसमें एक और वर्बोज़ फॉर्म दिया गया है जो काम करता है। अवांछित संदर्भों में अनुमत 'std :: declval 'के अस्तित्व पर ध्यान दें, शून्य सूचक चाल आवश्यक नहीं है :) –

5

आपका कोड अमान्य सी ++ 11 है, क्योंकि वर्ग किसी सदस्य फ़ंक्शन के रिटर्न प्रकार में पूर्ण नहीं है। आप केवल उन सदस्यों तक पहुंच सकते हैं जिन्हें पहले घोषित किया गया था। जैसा तो

class MyClass { 
private: 
    int _arg; 

public: 
    MyClass(int i): _arg(i) {} 

    template <typename F> 
    auto apply(F& f) -> decltype(f(_arg)) { 
    return f(_arg); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _arg)) { 
    return f(*this, _arg); 
    } 
}; 

Modulo हाँ का उपयोग कर कि, this सी ++ 11 ट्रेलिंग वापसी प्रकार में में मान्य है।

+0

आह, यह दिलचस्प है। मैंने इसके बारे में सोचा नहीं था, लेकिन अगर मैं सही से याद करता हूं, तो यह समझ में आता है, वही प्रकारों पर लागू होता है (यानी उन्हें कक्षाओं में भी उपयोग करने से पहले घोषित किया जाना चाहिए)। –

+0

कोई सदस्य सदस्य निकाय निकायों में कक्षा को पूर्ण माना जाता है। इसलिए बाद में घोषित सदस्य प्रकार भी दिखाई दे रहे हैं। –

+0

मैं विशेष रूप से [इस] (http://ideone.com/T1ZS8) के बारे में सोच रहा था: 'संरचना ए {प्रकार foo(); typedef int प्रकार; }; '। हमेशा मुझे पुरानी शैली * पार्सिंग के रूप में गड़बड़ कर दिया: x –

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