Is there a syntax to constraint a non-templated method? All the syntaxes I've tried on godbolt with clang concepts branch and gcc fail to compile:
// these examples do not compile
template <bool B>
struct X
{
requires B
void foo() {}
};
template <class T>
struct Y
{
requires (std::is_trivially_copyable_v<T>)
auto foo() {}
};
The trick to make it compile is the same trick you needed to do with SFINAE, make the methods template, even though they really are not templates. And funny enough, the constraint doesn't seem to need the method template, it can work fine on the class template alone, so I really hope there is a way to apply the constraints with concepts without having to resort to the old hacks:
// old hacks
template <bool B>
struct X
{
template <bool = B>
requires B
auto foo() {}
};
template <class T>
struct Y
{
template <class = T>
requires std::is_trivially_copyable_v<T>
auto foo() {}
};
Real life example:
template <class T, bool Copyable_buf = false>
struct Buffer
{
/* ... */
requires Copyable_buf
Buffer(const Buffer& other) {}
/* ... */
};
template <class T>
using Copyable_buffer = Buffer<T, true>;
To support the other answer on this, here is the normative wording about this, from the latest standard draft:
[dcl.decl]
1 A declarator declares a single variable, function, or type, within a declaration. The init-declarator-list appearing in a declaration is a comma-separated sequence of declarators, each of which can have an initializer.
init-declarator-list: init-declarator init-declarator-list , init-declarator init-declarator: declarator initializeropt declarator requires-clause4 The optional requires-clause ([temp]) in an init-declarator or member-declarator shall not be present when the declarator does not declare a function ([dcl.fct]). When present after a declarator, the requires-clause is called the trailing requires-clause. The trailing requires-clause introduces the constraint-expression that results from interpreting its constraint-logical-or-expression as a constraint-expression. [ Example:
void f1(int a) requires true; // OK auto f2(int a) -> bool requires true; // OK auto f3(int a) requires true -> bool; // error: requires-clause precedes trailing-return-type void (*pf)() requires true; // error: constraint on a variable void g(int (*)() requires true); // error: constraint on a parameter-declaration auto* p = new void(*)(char) requires true; // error: not a function declaration
— end example ]
As those two paragraphs specify, a trailing requires clause can appear at the end of function declarators. Its meaning is to constrain the function by the constant expression it accepts as an argument (which includes concepts).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With