【问题标题】:How to declare a concept for binary operations properly如何正确声明二进制操作的概念
【发布时间】:2021-06-21 10:55:11
【问题描述】:

我正在实现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;
}  

不幸的是,这两种方法都返回 false,我无法找到解决此问题的方法。

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

【问题讨论】:

  • 我不会为返回类型添加模板参数,而是将其设为auto,因为它允许integer promotion。此外,您编写它的方式是在计算后执行static_cast
  • 顺便说一句,不确定您的参数“正确性”:acca 可能是 R 类型(这不是必需的 std::integral
  • 为什么要将自己编写的所有概念都放入std命名空间?

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


【解决方案1】:

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

There is a 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>;

注意你可以更简洁地表达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;
}

【讨论】:

    猜你喜欢
    • 2016-03-20
    • 2016-04-20
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多