【发布时间】:2020-05-23 12:36:31
【问题描述】:
我有一个普通二元运算符的概念
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 <template <typename T> typename op> concept。使用概念时必须编写两次模板类型看起来很尴尬。 -
@Mansoor:不等价,检查类型似乎更自然,
is_binary_operation<std::plus<void>, double>也有意义。 -
你是什么意思但不是
std::plus?可以加两个doubles,怎么不实现呢? -
@Barry:我认为 OP 想检查
operator()的 签名。
标签: c++ c++20 c++-concepts