在 using 声明引入的折叠表达式中使用运算符是否合法?
Is it legal to use an operator in a fold expression that was introduced by a using declaration?
我正在尝试在折叠表达式中使用任意函数,当我发现以下代码可以用 gcc
编译但不能用 clang
编译时。
enum Enum {
A = 3,
B = 8,
C = 5
};
namespace EnumMax {
constexpr Enum operator>>=(const Enum left, const Enum right) {
return left < right ? right : left;
}
}
template<Enum ... enums>
constexpr Enum max() {
using EnumMax::operator>>=;
return (enums >>= ...);
}
constexpr Enum max_v = max<A, B, C>();
似乎clang
没有考虑重载运算符,而是尝试在折叠表达式中使用常规>>=
运算符。
然而,如果 fold 表达式被拼写出来,clang
会考虑重载运算符并且编译得很好:
constexpr Enum maxExplicit() {
using EnumMax::operator>>=;
return (A >>= (B >>= C));
}
这是 clang
错误吗?或者折叠表达式的拼写等价物不完全等价?
根据 [expr.prim.fold]/fold-operator:
fold-operator: one of
+ - * / % ^ & | << >>
+= -= *= /= %= ^= &= |= <<= >>= =
== != < > <= >= && || , .* ->*
所以>>=
是一个fold-operator.
An expression of the form (... <em>op</em> e)
where op
is a
fold-operator is called a unary left fold. An expression of the form (e <em>op</em> ...)
where op
is a fold-operator is
called a unary right fold. Unary left folds and unary right folds
are collectively called unary folds. In a unary fold, the
cast-expression shall contain an unexpanded pack ([temp.variadic]).
所以(enums >>= ...)
是一元右折。
The instantiation of a fold-expression produces:
[...]
E<sub>1</sub> <em>op</em> (⋯ <em>op</em> (E<sub><em>N</em>−1</sub> <em>op</em> E<sub><em>N</em></sub>))
for a unary right fold,
[...]
In each case, op
is the fold-operator, N
is the number of
elements in the pack expansion parameters, and each
E<sub><em>i</em></sub>
is generated by instantiating the pattern
and replacing each pack expansion parameter with its
i
th element. [...]
因此,(enums >>= ...)
在实例化时在语义上等同于 (A >>= (B >>= C))
。所以这是 Clang 中的一个错误。
我正在尝试在折叠表达式中使用任意函数,当我发现以下代码可以用 gcc
编译但不能用 clang
编译时。
enum Enum {
A = 3,
B = 8,
C = 5
};
namespace EnumMax {
constexpr Enum operator>>=(const Enum left, const Enum right) {
return left < right ? right : left;
}
}
template<Enum ... enums>
constexpr Enum max() {
using EnumMax::operator>>=;
return (enums >>= ...);
}
constexpr Enum max_v = max<A, B, C>();
似乎clang
没有考虑重载运算符,而是尝试在折叠表达式中使用常规>>=
运算符。
然而,如果 fold 表达式被拼写出来,clang
会考虑重载运算符并且编译得很好:
constexpr Enum maxExplicit() {
using EnumMax::operator>>=;
return (A >>= (B >>= C));
}
这是 clang
错误吗?或者折叠表达式的拼写等价物不完全等价?
根据 [expr.prim.fold]/fold-operator:
fold-operator: one of
+ - * / % ^ & | << >> += -= *= /= %= ^= &= |= <<= >>= = == != < > <= >= && || , .* ->*
所以>>=
是一个fold-operator.
An expression of the form
(... <em>op</em> e)
whereop
is a fold-operator is called a unary left fold. An expression of the form(e <em>op</em> ...)
whereop
is a fold-operator is called a unary right fold. Unary left folds and unary right folds are collectively called unary folds. In a unary fold, the cast-expression shall contain an unexpanded pack ([temp.variadic]).
所以(enums >>= ...)
是一元右折。
The instantiation of a fold-expression produces:
[...]
E<sub>1</sub> <em>op</em> (⋯ <em>op</em> (E<sub><em>N</em>−1</sub> <em>op</em> E<sub><em>N</em></sub>))
for a unary right fold,[...]
In each case,
op
is the fold-operator,N
is the number of elements in the pack expansion parameters, and eachE<sub><em>i</em></sub>
is generated by instantiating the pattern and replacing each pack expansion parameter with itsi
th element. [...]
因此,(enums >>= ...)
在实例化时在语义上等同于 (A >>= (B >>= C))
。所以这是 Clang 中的一个错误。