I wanted to use the TS concept to help me with data restriction. I will talk about the concepts discussed in p0121r0, and I use GCC 6.2 for tests.
Take this simple snippet of code:
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; };
I need to pass a test tester with the test property to the test, which is incremental and decrementing. Good.
struct A { unsigned test; } Tester<A> a;
It works as expected. Obviously, the following will not work:
struct B { std::string test; }; struct C { unsigned not_test; }; Tester<B> b;
Now, the real question is: why does the following not work?
class D { unsigned test; }; Tester<D> d;
I tried to look into the std document, but I canโt understand that this behavior is expected if std itself does not have this capability, if the compiler does not work correctly ...
Or maybe I need to declare some kind of friendship, but what's the point? This is a situation in which the limitations of concepts should not be limited to accessories ...
Any ideas on what's going on here?
EDIT: It's not easy to give an idea of โโthe problem with a simple example. This is a bit more complicated, but more like a real case:
#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); }
As you can see, it is obvious that the counter, loading and unloading should be confidential / secure and that they should be accessed only from Scoper. If I use an abstract base class, I can restrict the counter and unload, but not load (for which, as you can see, I donโt know how to handle the correct syntax ...).
This may not change your answers, but the problem is probably a little cleaner.