mthiffau
mthiffau

Reputation: 133

How to specify (declval?) a function pointer argument to a method in a concept 'requires' block?

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

Answers (0)

Related Questions