CppCoreGuidelines T.20 避免添加无意义的 concept
01 September 2023
“Avoid “concepts” without meaningful semantics”
理由
concept 是用来表达某个语义的标记,比如某个数字,某些元素的范围,或者能完全排序。简单的约束,比如有一个 + 操作符,有一个 > 操作符,等等,不一定能孤立地用来表达某个特定的意义。而应该是用来建立某个有意义的 concept。
坏例子
template<typename T> // bad; insufficient concept Addable = requires(T a, T b) { a+b; }; template<Addable N> auto algo(const N& a, const N& b) // use two numbers { // ... return a + b; } int x = 7; int y = 9; auto z = algo(x, y); // z = 16 string xx = "7"; string yy = "9"; auto zz = algo(xx, yy); // zz = "79"
这里可能可以对参数进行拼接。很可能会出错。定义对应的减号操作会给出完全不一样的可接受的类型参数。这个 Addable
违反了数学规则中加法可交换法则:
a+b == b+a
。
注意
一个正确的概念应该能够规定有意义的语义特性,而不是语法限制。
例子
template<typename T> // The operators +, -, *, and / for a number are assumed to follow the usual mathematical rules concept Number = requires(T a, T b) { a+b; a-b; a*b; a/b; }; template<Number N> auto algo(const N& a, const N& b) { // ... return a + b; } int x = 7; int y = 9; auto z = algo(x, y); // z = 16 string xx = "7"; string yy = "9"; auto zz = algo(xx, yy); // error: string is not a Number
注意
在概念中,规定多个操作可以减少某个单独操作造成的类型多重匹配的情况。
强化
- 标记在其他概念之外定义某个单独运算符操作的概念
- 标记使用
enable_if
模拟单独运算符操作的概念