有没有办法在c++11/c++14中将std::regular_invocable实现为type_trait样式函数?

问题描述 投票:0回答:1

我目前正在开发一个 Arduino“gameboy”风格的项目,我正在尝试制作一个像游戏引擎一样工作的库。在 Arduino IDE 中,使用 AVR 板时没有 C++ STL,因此我尝试实现标准模板库中的一堆内容,例如容器和类型特征。我目前正在尝试将 std::regular_invocable 实现为元函数,因为 Arduino IDE 中没有概念(从外观来看它编译为 c++14)。由于 std::regular_invocable 隐式依赖于 require 表达式,以确保一切都保持相等,因此我在 arduino IDE 中实现这一点时遇到了麻烦。我已经实现了 std::is_invocable 和 std::invoke 。

这是我的 std::invocable 实现:

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 { };

libstdc++ 中的 std::invocable 和 std::regular_invocable 实现:

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

我不熟悉 require 表达式的工作原理,因为我在较新的 C++ 版本中没有编写太多代码,但似乎您在参数中创建了未初始化的变量,您可以将其传递给函数并进行比较。

有没有什么方法可以检查可调用类型及其参数在 c++14 中调用后是否保持相等,而不依赖于 require 表达式来确保一切都保持相等?

如果这措辞不好或者这看起来很愚蠢,我很抱歉。我是自学成才的,这是我在任何地方发布的第一个编码问题。

我尝试使用 declval 使用 bool_constant 检查是否相等,但我无法弄清楚 找到一种将类型 _Fn&& 与传递给调用函数的 _Fn&& 进行比较的方法 因为 declval 必须不被评估。我需要能够在编译时检查是否 _Fn 类型的变量和 _Args 中的变量...调用后保持相等。

c++ c++14 type-traits arduino-c++
1个回答
0
投票

唯一的解决方案是使

regular_invocable
成为
invocable
的别名,就像标准库那样。不,它不会隐式检查相等性保留,编译器不能这样做。请参阅此处

© www.soinside.com 2019 - 2024. All rights reserved.