首页 > 解决方案 > 如何正确声明二进制操作的概念

问题描述

我正在实现elements of programming书中的通用快速功率算法。

这是一个非常幼稚的版本

template <typename R, typename I, typename Op>
requires std::integral<R> && std::integral<I> && std::is_binary_op<Op, R, I, I>
R power(I acc, I a, I n, Op op) {
  while (n-- != I{0}) {
    acc = op(acc, a);
  }
  return acc;
}

我也在尝试对传递给函数的类型强制执行要求。但是当我试图声明一个关于二进制操作的概念时,我被卡住了。这是我想出的两种方法。

// first approach
namespace std {
template <typename Op, typename Ret, typename Arg1, typename Arg2>
concept is_binary_op = std::is_same<Op, Ret(Arg1, Arg2)>::value;
}

// second approach
namespace std {
template <typename Op, typename Ret, typename Arg1, typename Arg2>
concept is_binary_op = std::is_same < typename std::function<Op>,
typename std::function<Ret(Arg1, Arg2)> >::value;
}  

不幸的是,这两种方法都返回错误,我找不到解决这个问题的方法。

  1. 知道如何解决这个问题吗?
  2. 为什么标准库中没有检查函数是一元还是二元等的概念...

提前致谢。

编辑:编译我收到的所有反馈后(感谢大家)。这是原始实现的更好版本。

namespace std {
template <typename Op, typename Arg1, typename Arg2>
concept binary_op = std::is_invocable<Op, Arg1, Arg2>::value;
}  // namespace std

template <std::integral I, std::binary_op<I, I> Op>
auto power(I acc, I a, I n, Op op) {
  while (n-- != I{0}) {
    acc = op(acc, a);
  }
  return acc;
}

标签: c++templatesc++20c++-concepts

解决方案


知道如何解决这个问题吗?为什么标准库中没有检查函数是一元还是二元等的概念...

对于特定的参数类型,有一个 trait 。您不应该将概念添加到namespace std.

template <typename Op, typename Arg1, typename Arg2>
concept binary_op = std::is_invocable_v<Op, Arg1, Arg2>;

template <typename Op, typename Ret, typename Arg1, typename Arg2>
concept binary_op_r = std::is_invocable_r_v<Ret, Op, Arg1, Arg2>;

NB 你可以power更简洁地表达

template <std::integral R, std::integral I, binary_op_r<R, I, I> Op>
requires std::is_assignable_v<I, R>
R power(I acc, I a, I n, Op op) {
  while (n-- != I{0}) {
    acc = op(acc, a);
  }
  return acc;
}

推荐阅读