2016-09-30 143 views
5

我想使用Concepts TS來幫助我處理數據約束。我將討論在p0121r0中討論的概念,並且我正在使用GCC 6.2進行測試。C++ TS概念和訪問器

藉此簡單的代碼:

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; 
}; 

我必須傳遞給結構測試儀與測試屬性,它是可遞增和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??? 

我試圖挖掘到STD紙,但我無法理解這是正常現象,如果STD本身缺少這種可能性,如果編譯器不能正常工作......

或者我可能需要宣佈某種友誼,但是有什麼意義呢?在這種情況下,概念約束不需要被訪問者約束 ...

任何關於這裏發生了什麼的想法?

編輯: 通過一個簡單的例子並不總是容易給出這個問題的想法。這一個是更復雜一點,但更類似於真實的案例:

#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); 
} 

正如你所看到的,很明顯,計數器負載卸載必須是私人/保護,而且他們只需要從Scoper訪問。 如果我使用一個抽象基類,我只能約束計數器卸載,但不負載(爲此,你可以看到,我不知道如何處理正確的語法......)。

也許這不會改變你的答案,但問題可能是一點點清潔。

回答

9

這個概念:

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

要求T公開訪問成員test既後可遞增和decrementable後。

此類型:

class D 
{ 
    unsigned test; 
}; 

沒有可公開訪問的構件測試。畢竟,我不能寫任何這些語句:

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

因此,D不符合概念test_is_availabletest是非常不可用。

如果您想Dtest_is_available,您需要製作testpublic。你不能簡單地使用friend的東西,這只是打破了概念系統 - 最終你會得到一個D,這是test_is_available對某些類型而不是其他類型。事實並非如此。

+0

因此,你只是說沒有辦法*要求*的會員,沒有可訪問性限制? – dodomorandi

+0

我_think_你可以把'Tester'類標記爲朋友,它也應該提供這個概念的私人訪問。儘管我沒有太多的概念,但我可能是錯的。 – Bitwize

+5

@dodomorandi這是'私人'的點。 – Barry