2016-09-30 11 views
5

私はコンセプト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; 
}; 

私は構造体のテスターに​​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??? 

STD自体はこの可能性を欠落している場合、コンパイラが正しく動作していない場合、私は

...、STD紙に掘ることを試みたが、私はこの動作を理解することはできませんよが期待されています

または、ある種の友情を宣言する必要があるかもしれませんが、何がポイントになるのでしょうか?これは、コンセプト制約がアクセッサによってに制限されている必要がない状況です。

ここで何が起こっているか考えてください。

編集: 簡単な例で問題のアイデアを伝えるのは必ずしも容易ではありません。この1は、実際のケースにもう少し複雑な、しかし、より似ています

あなたが見ることができるように
#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は、ポストincrementableとポストdecrementable両方で公にアクセスメンバーtestを持っていることが必要です。

このタイプ:

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

私はあなたに 'Tester'クラスを友人としてマークすることができますし、そのコンセプトへの私的アクセスも提供するはずです。私はあまりコンセプトで遊んでいないので、間違っているかもしれません。 – Bitwize

+5

@ドドモランディこれは、プライベートのポイントのようなものです。 – Barry

関連する問題