gpt4 book ai didi

复合赋值运算符的 C++ 概念

转载 作者:行者123 更新时间:2023-12-01 14:57:38 28 4
gpt4 key购买 nike

我有一个普通二元运算符的概念

template<typename Op, typename T> concept is_binary_operation =
requires (const T& t1, const T& t2) // e.g. a+b
{
{Op()(t1,t2)}->std::convertible_to<T>;
};

以及复合赋值运算符的概念
template<typename Op, typename T> concept is_operation_and_assign =
requires (T& t1, const T& t2) // e.g a += b;
{
{Op()(t1,t2)}->std::convertible_to<T>;
};

对于复合赋值运算符,这按预期工作:
template<typename T> struct op_and_assign
{
T& operator()(T& t1, const T& t2)
{
t1 += t2;
return t1;
}
};

这个“is_operation_and_assign”而不是“is_binary_operation”
std::cout << is_binary_operation<op_and_assign<double>, double> << " ";
std::cout << is_operation_and_assign<op_and_assign<double>, double> << std::endl;

打印“0 1”。然而,std::plus 满足这两个概念:
std::cout << is_binary_operation<std::plus<double>, double> << " ";
std::cout << is_operation_and_assign<std::plus<double>, double> << std::endl;

打印“1 1”。

如何更改“is_operation_and_assign”的概念,以便获得输出“1 0”,即它将由 op_and_assign 而不是由 std::plus 实现?

为了更清楚我需要什么:我有两个版本的算法,一个使用复合赋值运算符,一个使用二元运算符:
template<typename Op, typename T>
int f() requires is_operation_and_assign<Op, T>
{
return 0;
}
template<typename Op, typename T>
int f() requires is_binary_operation<Op, T>
{
return 1;
}

我可以调用 op_and_assign 的版本
f<op_and_assign<double>, double>();

但 std::plus 的版本
f<std::plus<double>, double>();

不编译。 (错误:对“f”的调用不明确)

更新 : 同时我找到了一个解决方法:

当我简单地添加 && !is_binary_operation<Op, T>到第一个 f :
template<typename Op, typename T>
int f() requires (is_operation_and_assign<Op, T>
&& !is_binary_operation<Op, T>)
{
return 0;
}
template<typename Op, typename T>
int f() requires is_binary_operation<Op, T>
{
return 1;
}

那么第二个电话不再模棱两可,即两者
f<op_and_assign<double>, double>();
f<std::plus<double>, double>();

编译(并选择所需的功能)。

最佳答案

澄清你的概念实际上在检查什么很重要,因为它不是你想象的那样。

这:

template<typename Op, typename T> concept is_operation_and_assign =
requires (T& t1, const T& t2) // e.g a += b;
{
{Op()(t1,t2)}->std::convertible_to<T>;
};

检查您是否可以调用 Op()(t1, t2)T&T const&并且你得到满足 convertible_to<T>的东西.当您提供:
template<typename T> struct op_and_assign
{
T& operator()(T& t1, const T& t2)
{
t1 += t2;
return t1;
}
};

作为第一个模板参数,它实际上检查了什么?这是一个未计算的表达式,我们正在检查是否可以调用 op_and_assign<T>() .我们没有评估调用运算符(operator)的主体,我们只是检查它是否是一个有效的调用。所以这与我们写的没有什么不同:
template<typename T> struct op_and_assign
{
T& operator()(T& t1, const T& t2);
};

它没有被评估,没有实体,所以唯一重要的是约束。这里没有约束,所以 op_and_assign只要参数是可转换的,它总是可以调用的。

当你这样做时:
is_binary_operation<op_and_assign<double>, double>

您实际上是在询问是否可以适本地转换参数。对于 is_binary_operation ,您提供了两个 double const& 类型的参数(来自您的 requires 表达式)但是 op_and_assign<double>需要拍一张 double& .这就是为什么此特定检查不起作用的原因。

对于如何修复它。 op_and_assign应该看起来像这样:
struct op_and_assign
{
template <typename T, typename U>
auto operator()(T&& t, U&& u) const -> decltype(t += u);
};

现在我们实际上正在检查是否可以执行 += .

但这不会改变您无法分配给 double const& 的情况。 .即使您没有进行您打算进行的检查,您也会在那里得到正确的答案。

关于复合赋值运算符的 C++ 概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61972143/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com