在using声明引入的fold表达式中使用运算符是否合法?

Mar*_*ark 19 c++ clang fold-expression c++17

当我发现以下可编译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>();
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/-LOudM

似乎clang不考虑重载运算符,而是尝试>>=在fold表达式中使用正则运算符。

但是,如果改写了fold表达式,clang则考虑重载运算符,并且可以正常编译:

constexpr Enum maxExplicit() {
    using EnumMax::operator>>=;
    return (A >>= (B >>= C));
}
Run Code Online (Sandbox Code Playgroud)

这是clang错误吗?还是等于折叠表达式的拼写不完全相同?

L. *_* F. 3

每个[expr.prim.fold]/折叠运算符

\n\n
\n

折叠运算符:其中之一

\n\n
+ \xe2\x80\x83\xe2\x80\x82- \xe2\x80\x83\xe2\x80\x82* \xe2\x80\x83\xe2\x80\x82/ \xe2\x80\x83\xe2\x80\x82% \xe2\x80\x83\xe2\x80\x82^ \xe2\x80\x83\xe2\x80\x82& \xe2\x80\x83\xe2\x80\x82| \xe2\x80\x83\xe2\x80\x82<< \xe2\x80\x83\xe2\x80\x82>> \n+=\xe2\x80\x83\xe2\x80\x82-=\xe2\x80\x83\xe2\x80\x82*=\xe2\x80\x83\xe2\x80\x82/=\xe2\x80\x83\xe2\x80\x82%=\xe2\x80\x83\xe2\x80\x82^=\xe2\x80\x83\xe2\x80\x82&=\xe2\x80\x83\xe2\x80\x82|=\xe2\x80\x83\xe2\x80\x82<<=\xe2\x80\x83\xe2\x80\x82>>=\xe2\x80\x83\xe2\x80\x82=\n==\xe2\x80\x83\xe2\x80\x82!=\xe2\x80\x83\xe2\x80\x82< \xe2\x80\x83\xe2\x80\x82> \xe2\x80\x83\xe2\x80\x82<=\xe2\x80\x83\xe2\x80\x82>=\xe2\x80\x83\xe2\x80\x82&&\xe2\x80\x83\xe2\x80\x82||\xe2\x80\x83\xe2\x80\x82,  \xe2\x80\x83\xe2\x80\x82.* \xe2\x80\x83\xe2\x80\x82->*\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

折叠运算符>>=也是如此。

\n\n

[expr.prim.fold]/2

\n\n
\n

形式为\n 折叠运算符的表达式称为一 折叠。形式为折叠运算符的表达式称为一元右折叠。一元左折叠和一元右折叠\n统称为一元折叠。在一元折叠中, 强制转换表达式应包含未展开的包 ([temp.variadic])。(... op e)op(e op ...)op

\n
\n\n

(enums >>= ...)一元右折叠也是如此。

\n\n

[temp.variadic]/10

\n\n
\n

折叠表达式的实例化产生:

\n\n
    \n
  • [...]

  • \n
  • E1 op (\xe2\x8b\xaf op (EN\xe2\x88\x921 op EN))对于一元右折叠,

  • \n
  • [...]

  • \n
\n\n

在每种情况下,op折叠运算符N是包扩展参数中的\n 个元素,每个\n 是通过实例化模式\n 并将每个包扩展参数替换为其 \n 个元素而生成的。[...]Eii

\n
\n\n

因此,(enums >>= ...)在语义上等同于(A >>= (B >>= C))实例化它。所以这是 Clang 中的一个错误。

\n