I have a simple code snippet below, which compiles using:
g++-9 -std=c++2a -fconcepts
This is trying to define a concept that requires the presence of a function. I would expect the output to be "yes" but it's not... Any idea why? Thanks.
#include <iostream>
template <typename T>
concept bool HasFunc1 =
requires(T) {
{ T::func1() } -> int;
};
struct Test
{
int func1()
{
return 5;
}
};
int main()
{
if constexpr (HasFunc1<Test>)
std::cout << "yes\n";
}
You are testing for presence of a static member function. What you want is
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
Try calling it yourself:
Test::func1();
prog.cc: In function 'int main()':
prog.cc:19:14: error: cannot call member function 'int Test::func1()' without object
19 | Test::func1();
| ^
Oh, right. func1
should either be a static
member function, or you should call it on an instance inside your concept:
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
@makogan asked (buried 19 deep in comments): what if func has arguments?
The answer is: for simple cases, manufacture parameters using constructors, or new expression. (Not particularly readable, but way more readable than the probably correct way given below).
template <typename T>
concept HasFunc1 =
requires(T t) {
{ t.func1( int() ) } -> std::same_as<int>;
};
For more complex examples, you can declare test parameters in the requires clause argument list:
concept IsCoServiceImplementation = requires(
T t,
CoServiceReply<typename T::return_type> *completionCallback)
{
{ T::return_type };
{t.OnSuspend(completionCallback) };
{t.OnCancel(completionCallback) };
};
This concept does have the desired intent (for me): it mostly converts nested-10-deep error messages about failures to meet a template contract into almost readable first-level error messages.
There's still a strange disconnect between the required code and the concept. It would be really nice to have tighter constraints on parameter types. And testing const-ness is grimly difficult. Far from the feature I had hope for. :-(
I'm still struggling with c++20 features. I'm open to suggestions as to how to do this better.
(A CoService, in case you're wondering, is an experimental attempt I'm working on to make it easier to marshal coroutine code back onto non-coroutine code with minimum fuss and bother).
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