C++17:"operator with precedence below cast"在"fold"概念中是什么意思?
C++17: What does "operator with precedence below cast" mean in "fold" concept?
http://en.cppreference.com/w/cpp/language/fold的网站给出了如何使用折叠概念的例子,上面写着:
Note
If the expression used as init or as pack has an operator with precedence
below cast at the top level, it can be parenthesed:
template<typename ...Args>
int sum(Args&&... args) {
// return (args + ... + 1 * 2); // Error: operator with precedence below cast
return (args + ... + (1 * 2)); // OK
}
作为一个非英语母语的人,我不放弃得到句子:
has an operator with precedence below cast at the top level
具体是什么意思,举个例子,说明什么?
你能帮忙解释一下吗?
非常感谢。
转换运算符 ((Typename)expr
) 在 C++'s operator precedence rules 中具有非常高的优先级。很少有运算符具有比这更高的优先级。 cast 级别或更高优先级的运算符是非常特殊的运算符,通常应用于单个表达式。
在表达式 args + ... + 1 * 2
中,...
应用于左侧和右侧的所有内容。但是 "on the right" 到底是什么意思呢?它只表示 + 1
部分,还是表示 + 1 * 2
?
对于具有高优先级的运算符,其意图很明显。例如,args + ... + func()
,显然 ()
函数调用运算符适用于 func
而不是 args + ... + func
。您不太可能想要后者,如果您这样做的话,您将不得不显式地使用括号 ((args + ... + func)()
)。
然而,对于图表中低于 3 的优先级,人们的理解变得更加模糊。因此,C++ 没有使用正常的优先级规则,而是强制用户对其进行明确说明。您可以设置 args + ... + (1 * 2)
或 (args + ... + 1) * 2
。但是你要清楚自己想要哪一个。
表示如果有多个运算符的表达式有歧义,"above cast"的运算符会在cast运算符之前调用,"below cast"的运算符会在cast运算符之后调用。如 2 + 2 * 2
乘法应该在加法之前执行,结果是 6,而不是 8。
让我们考虑以下两个 类,它们是 castable 彼此:
class E2;
class E1 {
public:
operator E2();
E1 operator++(int) {
std::cout << "E1 Post-inc\n";
return *this;
}
E1 operator*(const E1&) {
std::cout << "E1 * E1\n";
return *this;
}
};
class E2 {
public:
operator E1() {
std::cout << "Cast E1 -> E2\n";
return E1();
}
E2 operator++(int) {
std::cout << "E2 Post-inc\n";
return *this;
}
E2 operator*(const E2&) {
std::cout << "E2 * E2\n";
return *this;
}
};
E1::operator E2() {
std::cout << "Cast E2 -> E1\n";
return E2();
}
那我们就声明一下吧
E1 e1;
E2 e2;
并做
(E1)e2++;
E1 和E2 都有运算符++
,那么这个表达式首先应该做什么:强制转换还是递增? Precedence table 回答说增量应该先完成,所以程序打印
E2 Post-inc
Cast E1 -> E2
那么,我们来试一个更复杂的例子:
e1 * (E1)e2++;
这里我们有 3 个动作(按照它们在代码中出现的顺序):乘法、转换和递增。如果执行将是什么顺序? Precedence table 表示增量是第一个,转换是第二个(它在增量下方),乘法是最后一个,因为它在它们两者之下。所以输出将是:
E2 Post-inc
Cast E1 -> E2
E1 * E1
请注意,您可以使用括号轻松地重新排序操作。例如,如果我们将 e1 * (E1)e2++;
替换为 (e1 * (E1)e2)++;
,我们将得到
Cast E1 -> E2
E1 * E1
E1 Post-inc
http://en.cppreference.com/w/cpp/language/fold的网站给出了如何使用折叠概念的例子,上面写着:
Note
If the expression used as init or as pack has an operator with precedence
below cast at the top level, it can be parenthesed:
template<typename ...Args>
int sum(Args&&... args) {
// return (args + ... + 1 * 2); // Error: operator with precedence below cast
return (args + ... + (1 * 2)); // OK
}
作为一个非英语母语的人,我不放弃得到句子:
has an operator with precedence below cast at the top level
具体是什么意思,举个例子,说明什么? 你能帮忙解释一下吗?
非常感谢。
转换运算符 ((Typename)expr
) 在 C++'s operator precedence rules 中具有非常高的优先级。很少有运算符具有比这更高的优先级。 cast 级别或更高优先级的运算符是非常特殊的运算符,通常应用于单个表达式。
在表达式 args + ... + 1 * 2
中,...
应用于左侧和右侧的所有内容。但是 "on the right" 到底是什么意思呢?它只表示 + 1
部分,还是表示 + 1 * 2
?
对于具有高优先级的运算符,其意图很明显。例如,args + ... + func()
,显然 ()
函数调用运算符适用于 func
而不是 args + ... + func
。您不太可能想要后者,如果您这样做的话,您将不得不显式地使用括号 ((args + ... + func)()
)。
然而,对于图表中低于 3 的优先级,人们的理解变得更加模糊。因此,C++ 没有使用正常的优先级规则,而是强制用户对其进行明确说明。您可以设置 args + ... + (1 * 2)
或 (args + ... + 1) * 2
。但是你要清楚自己想要哪一个。
表示如果有多个运算符的表达式有歧义,"above cast"的运算符会在cast运算符之前调用,"below cast"的运算符会在cast运算符之后调用。如 2 + 2 * 2
乘法应该在加法之前执行,结果是 6,而不是 8。
让我们考虑以下两个 类,它们是 castable 彼此:
class E2;
class E1 {
public:
operator E2();
E1 operator++(int) {
std::cout << "E1 Post-inc\n";
return *this;
}
E1 operator*(const E1&) {
std::cout << "E1 * E1\n";
return *this;
}
};
class E2 {
public:
operator E1() {
std::cout << "Cast E1 -> E2\n";
return E1();
}
E2 operator++(int) {
std::cout << "E2 Post-inc\n";
return *this;
}
E2 operator*(const E2&) {
std::cout << "E2 * E2\n";
return *this;
}
};
E1::operator E2() {
std::cout << "Cast E2 -> E1\n";
return E2();
}
那我们就声明一下吧
E1 e1;
E2 e2;
并做
(E1)e2++;
E1 和E2 都有运算符++
,那么这个表达式首先应该做什么:强制转换还是递增? Precedence table 回答说增量应该先完成,所以程序打印
E2 Post-inc
Cast E1 -> E2
那么,我们来试一个更复杂的例子:
e1 * (E1)e2++;
这里我们有 3 个动作(按照它们在代码中出现的顺序):乘法、转换和递增。如果执行将是什么顺序? Precedence table 表示增量是第一个,转换是第二个(它在增量下方),乘法是最后一个,因为它在它们两者之下。所以输出将是:
E2 Post-inc
Cast E1 -> E2
E1 * E1
请注意,您可以使用括号轻松地重新排序操作。例如,如果我们将 e1 * (E1)e2++;
替换为 (e1 * (E1)e2)++;
,我们将得到
Cast E1 -> E2
E1 * E1
E1 Post-inc