5

Concepts TS を使用して、データの制約を支援したいと考えていました。p0121r0で説明したコンセプトについてお話しします。テストには GCC 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;
};

インクリメントおよびデクリメント可能なtestプロパティを持つ型を struct Tester に渡す必要があります。良い。

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

ご覧のとおり、counterload、およびunloadは非公開/保護する必要があり、 Scoperからのみアクセスする必要があることは明らかです。抽象基本クラスを使用すると、 counterunloadのみを制約できますが、 loadはできません (ご覧のとおり、正しい構文を処理する方法がわかりません...)。

これで答えが変わることはないかもしれませんが、問題はおそらく少しきれいになります。

4

1 に答える 1

10

このコンセプト:

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

post-incrementable と post-decrementable の両方でパブリックにアクセス可能なメンバーTが必要です。test

このタイプ:

class D
{
    unsigned test;
};

一般にアクセス可能なメンバー テストはありません。結局のところ、私はこれらのステートメントを書くことはできません:

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

したがって、D概念を満たしていませんtest_is_availabletest非常に利用できません。

になりたい場合Dtest_is_available、作成する必要がありますtest publicfriend概念システムを壊すだけの何かを単純化することはできません。最終的には、一部Dtest_is_availableタイプには適用されますが、他のタイプには適用されない になります。それは物事がうまくいくはずの方法ではありません。

于 2016-09-30T13:12:52.680 に答える