Note: everything that follows uses the Concepts TS implementation in GCC 6.1
Let's say I have a concept Surface
, like the following:
template <typename T>
concept bool Surface() {
return requires(T& t, point2f p, float radius) {
{ t.move_to(p) };
{ t.line_to(p) };
{ t.arc(p, radius) };
// etc...
};
}
Now I want to define another concept, Drawable
, which matches any type with a member function:
template <typename S>
requires Surface<S>()
void draw(S& surface) const;
i.e.
struct triangle {
void draw(Surface& surface) const;
};
static_assert(Drawable<triangle>(), ""); // Should pass
That is, a Drawable
is something which has a templated const member function draw()
taking an lvalue reference to something which satisfies the Surface
requirements. This is reasonably easy to specify in words, but I can't quite work out how to do it in C++ with the Concepts TS. The "obvious" syntax doesn't work:
template <typename T>
concept bool Drawable() {
return requires(const T& t, Surface& surface) {
{ t.draw(surface) } -> void;
};
}
error: 'auto' parameter not permitted in this context
Adding a second template parameter allows the concept definition to compile, but:
template <typename T, Surface S>
concept bool Drawable() {
return requires(const T& t, S& s) {
{ t.draw(s) };
};
}
static_assert(Drawable<triangle>(), "");
template argument deduction/substitution failed: couldn't deduce template parameter 'S'
now we can only check whether a particular <Drawable
, Surface
> pair matches the Drawable
concept, which isn't quite right. (A type D
either has the required member function or it does not: that doesn't depend on which particular Surface
we check.)
I'm sure it's possible to do what I'm after, but I can't work out the syntax and there aren't too many examples online yet. Does anybody know how to write a concept definition which requires type to have a constrained template member function?