2016-09-30 9 views
5

मैं डेटा बाधा के साथ मेरी मदद करने के लिए अवधारणाओं टीएस का उपयोग करना चाहता था। मैं p0121r0 में चर्चा की गई अवधारणाओं के बारे में बात करूंगा और मैं परीक्षणों के लिए जीसीसी 6.2 का उपयोग कर रहा हूं।सी ++ टीएस अवधारणाओं और एक्सेसर्स

कोड के इस सरल टुकड़ा लें:

template<typename T> 
concept bool test_is_available = requires(T t) { 
    t.test; 
    { t.test++ }; 
    { t.test-- }; 
}; 

template<test_is_available T> 
struct Tester 
{ 
    T t; 
}; 

मैं struct परीक्षक को परीक्षण संपत्ति है, जो incrementable और decrementable है के साथ एक प्रकार पारित करने के लिए की है। अच्छा।

struct A 
{ 
    unsigned test; 
} 

Tester<A> a; 

अपेक्षित कार्य करता है। जाहिर है, के बाद एक काम करेंगे नहीं:

struct B 
{ 
    std::string test; 
}; 

struct C 
{ 
    unsigned not_test; 
}; 

Tester<B> b; // error: test++ and test-- are ill formed 
Tester<C> c; // error: no test available 

अब, असली सवाल: क्यों के बाद एक काम नहीं कर रहा?

class D 
{ 
    unsigned test; 
}; 

Tester<D> d; // error: private??? 

मैं एसटीडी कागज में खुदाई करने के लिए कोशिश की, लेकिन मैं इस व्यवहार को समझने में सक्षम होने की उम्मीद है, अगर एसटीडी ही इस संभावना याद आ रही है, अगर संकलक सही ढंग से काम नहीं कर रहा है नहीं कर रहा हूँ ...

या शायद मुझे दोस्ती की घोषणा करने की ज़रूरत है, लेकिन क्या बात हो सकती है? यह एक ऐसी स्थिति है जिसमें अवधारणाओं की बाधाओं को को एक्सेसर्स द्वारा बाधित नहीं किया जाता है ...

यहां क्या हो रहा है इसके बारे में कोई विचार?

संपादित करें: एक साधारण उदाहरण के साथ समस्या का विचार देना हमेशा आसान नहीं होता है। यह एक असली मामले के लिए थोड़ा और अधिक जटिल है, लेकिन अधिक समान है:

#include <cassert> 
#include <utility> 

template<typename T> 
concept bool Countable = requires(T t) { 
    t.counter; 
    { ++t.counter }; 
    { --t.counter }; 
    //{ t.load(auto&&...) } -> void; <-- I am not sure how to handle this 
    { t.unload() } -> void; 
}; 

template<Countable T> 
class Scoper 
{ 
public: 
    template<typename... Args> 
    Scoper(T& t, Args... args) : m_t(&t) 
    { 
     ++t.counter; 
     t.load(std::forward<Args>(args)...); 
    } 

    ~Scoper() 
    { 
     --m_t->counter; 
     m_t->unload(); 
    } 

private: 
    T* m_t; 
}; 

class Scopeable 
{ 
public: 
    unsigned getCounter() const 
    { 
     return counter; 
    } 

//private: 
    //template<Countable> friend class Scoper; <-- does not work 
    void load(char, int) {} 
    void unload() {} 
    unsigned counter = 0; 
}; 

int main() 
{ 
    Scopeable scopeable; 
    assert(scopeable.getCounter() == 0); 
    { 
     Scoper<Scopeable> scoper(scopeable, 'A', 2); 
     assert(scopeable.getCounter() == 1); 
    } 
    assert(scopeable.getCounter() == 0); 
} 

आप देख सकते हैं, यह स्पष्ट है कि काउंटर, लोड और अनलोड निजी/संरक्षित रहना होगा, और उन्हें केवल स्कूपर से एक्सेस किया जाना है। अगर मैं एक सार आधार वर्ग का उपयोग मैं केवल काउंटर और अनलोड, लेकिन में रोके नहीं कर सकते लोड (, जिसके लिए के रूप में आप देख सकते हैं, मैं कैसे सही सिंटैक्स को संभालने के लिए ... पता नहीं है)।

शायद यह आपके उत्तरों को नहीं बदलेगा, लेकिन समस्या शायद थोड़ा सा क्लीनर है।

उत्तर

9

इस अवधारणा:

template<typename T> 
concept bool test_is_available = requires(T t) { 
    t.test; 
    { t.test++ }; 
    { t.test-- }; 
}; 

की आवश्यकता है कि T एक सार्वजनिक रूप से सुलभ सदस्य test है कि दोनों के बाद incrementable और बाद decrementable है।

इस प्रकार:

class D 
{ 
    unsigned test; 
}; 

एक सार्वजनिक रूप से सुलभ सदस्य परीक्षण नहीं है।सब के बाद, मैं उन बयानों के किसी भी नहीं लिख सकते हैं:

D d; 
d.test; // error 
d.test++; // error 
d.test--; // error 

इसलिए, D अवधारणा test_is_available को पूरा नहीं करता। test बहुत अधिक उपलब्ध नहीं है।

यदि आप Dtest_is_available होने के लिए चाहते हैं, तो आपको testpublic बनाना होगा। आप बस friend कुछ नहीं कर सकते हैं, जो केवल अवधारणा प्रणाली को तोड़ता है - आप D के साथ समाप्त हो जाएंगे जो test_is_available कुछ प्रकारों पर है लेकिन दूसरों को नहीं। वास्तव में यह नहीं है कि चीजों को कैसे काम करना चाहिए।

+0

इसलिए, आप बस इतना कह रहे हैं कि किसी सदस्य के लिए * पूछने के लिए कोई रास्ता नहीं है, बिना पहुंच प्रतिबंध के? – dodomorandi

+0

मैं _think_ आप 'परीक्षक' वर्ग को एक दोस्त के रूप में चिह्नित कर सकता हूं और इसे अवधारणा के लिए भी निजी पहुंच प्रदान करनी चाहिए। मैंने अवधारणाओं के साथ बहुत ज्यादा खेला नहीं है, इसलिए मैं गलत हो सकता हूं। – Bitwize

+5

@dodomorandi यह 'निजी' का मुद्दा है। – Barry

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