c++c++14type-traitsarduino-c++

Is there a way to implement std::regular_invocable as a type_trait style function in c++11/c++14?


I'm currently working on an Arduino "gameboy" style project where I'm trying to make a library that will work like a game engine. In the Arduino IDE there is no c++ STL when using an AVR board, so I'm trying to implement a bunch of stuff from the standard template library such as containers and type traits. I'm currently trying to implement std::regular_invocable as a meta-function since there are no concepts in the Arduino IDE(it compiles to c++14 from the looks of it). Since std::regular_invocable relies on the requires expression implicitly making sure everything is equality preserving I'm having trouble implementing this in the arduino IDE. I have std::is_invocable and std::invoke implemented.

here is my std::invocable implementation:

namespace __detail {
  
  struct __do_invocable_concept_impl {
    template<class _Fn, class... _Args,
      class = decltype(invoke(forward<_Fn>(declval<_Fn&&>()), forward<_Args>(declval<_Args&&>())...))>
    static true_type __test(int);

    template<class, class>
    static false_type __test(...);
  };

  template<class _Fn, class... _Args>
  struct __invocable_concept_impl : public __do_invocable_concept_impl {
    using type = decltype(__test<_Fn, _Args...>(0));
  };

}

template<class _Fn, class... _Args>
struct invocable 
  : public __detail::__invocable_concept_impl<_Fn, _Args...>::type { };

std::invocable and std::regular_invocable implementation in libstdc++:

template<class _Fn, class... _Args>
concept invocable = 
  requires(_Fn&& __f, _Args&&... __args) {
    invoke(forward<_Fn>(__f), forward<_Args>(__args)...);
  };

template<class _Fn, class... _Args>
concept regular_invocable = invocable<_Fn, _Args...>; 
// this automatically checks for equality preservation

I'm not familiar with how the requires expression works as I haven't coded much in the newer c++ versions, but it seems like you create uninitialized variables in the parameters which you can pass to a function and do comparisons with.

Is there any way to check if the invocable type and its arguments preserve equality after being invoked in c++14 without relying on the requires expression making sure everything is equality preserving?

Sorry if this is worded poorly or if this seems dumb. I'm self taught and this is the first coding question I ever posted anywhere.

I've tried to use declval to check for equality using bool_constant, but I can't figure out a way to compare type _Fn&& with the _Fn&& that was passed to the invoke function since declval must be unevaluated. I need to be able to check at compile time if a variable of type _Fn and the variables in _Args... stay equal after invoking.


Solution

  • The only solution is to make regular_invocable an alias of invocable, like the standard library does. No, it doesn’t implicitly check for equality preservation, the compiler can’t do that. See here.