Reputation: 133
I have a scheduler class template that I'd like to use with one of several timer classes. I'd like to use a concept to verify a given timer class has what the scheduler needs.
// One of several that will follow this pattern.
class Timer8 {
public:
//...
using overflow_context = OverflowIrqCtx; // a struct.
using overflow_handler = void(*)(overflow_context* ovf_ctx, void* usr_ctx);
void SetOverflowIrqEnabled(bool enabled);
void SetOverflowIrqHandler(void* usr_ctx, overflow_handler handler);
//...
};
However the following does not compile:
template<typename T>
concept Timer = requires(T a) {
{ a.SetOverflowIrqEnabled(std::declval<bool>()) };
{ a.SetOverflowIrqHandler(std::declval<void*>(), std::declval<typename T::overflow_handler>()) };
};
The error is:
scheduler.h: In substitution of 'template<class T> requires Timer<T> class embedded::Scheduler [with T = embedded::time::Timer8]':
scheduler_test.cc:20:45: required from here
scheduler.h:16:9: required for the satisfaction of 'Timer<T>' [with T = embedded::time::Timer8]
scheduler.h:16:17: in requirements with 'T a' [with T = embedded::time::Timer8]
scheduler.h:22:28: note: the required expression 'a.SetOverflowIrqHandler(std::declval<void*>(), declval<typename T::overflow_handler>())' is invalid, because
22 | { a.SetOverflowIrqHandler(std::declval<void*>(), std::declval<typename T::overflow_handler>()) };
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If I remove the function pointer declval and replace it with nullptr
it compiles, but I don't think that's testing what I want it to test.
What would be the correct way to specify that a method must take a particular function pointer type as an argument in a concept? Is there some syntax gotcha I'm missing? Thanks!
Upvotes: 1
Views: 94