C++ TS概念和访问器

dod*_*ndi 5 c++ c++-concepts c++20

我想使用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;
};
Run Code Online (Sandbox Code Playgroud)

我必须向struct Tester传递一个带有test属性的类型,该属性是可递增和可递减的.好.

struct A
{
    unsigned test;
}

Tester<A> a;
Run Code Online (Sandbox Code Playgroud)

按预期工作.显然,以下一个不起作用:

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
Run Code Online (Sandbox Code Playgroud)

现在,真正的问题是:为什么以下一个不起作用?

class D
{
    unsigned test;
};

Tester<D> d; // error: private???
Run Code Online (Sandbox Code Playgroud)

我试图深入研究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);
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,很明显,计数器,加载卸载必须是私有/受保护的,并且只需从Scoper访问它们.如果我使用抽象基类,我只能约束计数器卸载,但不能加载(正如你所看到的,我不知道如何处理正确的语法...).

也许这不会改变你的答案,但问题可能有点清洁.

Bar*_*rry 10

这个概念:

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

要求T具有可公开访问的成员test,该成员既可以后递增又可以递减.

这个类型:

class D
{
    unsigned test;
};
Run Code Online (Sandbox Code Playgroud)

没有可公开访问的成员测试.毕竟,我不能写任何这些陈述:

D d;
d.test;   // error
d.test++; // error
d.test--; // error
Run Code Online (Sandbox Code Playgroud)

因此,D不符合这个概念test_is_available.test非常不可用.

如果你想D成为一个test_is_available,你需要做test public.你不能简单的friend东西,只是打破了理念体系-你会得到一个最终D这是test_is_available某些类型而不是其他.事实并非如此.

  • @dodomorandi这就是"私人"的观点. (5认同)