I was experimenting with using arbitrary functions in fold expressions, when I found the following code that compiles with gcc
but does not compile with 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>();
https://godbolt.org/z/-LOudM
It seems that clang
does not consider the overloaded operator, but attempts to use the regular >>=
operator in the fold expression.
However, if instead the fold expression is spelled out, clang
does consider the overloaded operator and will compile just fine:
constexpr Enum maxExplicit() {
using EnumMax::operator>>=;
return (A >>= (B >>= C));
}
Is this a clang
bug? Or is the spelled out equivalent of a fold expression not exactly equivalent?
Per [expr.prim.fold]/fold-operator:
fold-operator: one of
+ - * / % ^ & | << >> += -= *= /= %= ^= &= |= <<= >>= = == != < > <= >= && || , .* ->*
So >>=
is a fold-operator.
Per [expr.prim.fold]/2:
An expression of the form
(... op e)
whereop
is a fold-operator is called a unary left fold. An expression of the form(e op ...)
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]).
So (enums >>= ...)
is a unary right fold.
Per [temp.variadic]/10:
The instantiation of a fold-expression produces:
[...]
E1op (⋯ op (EN−1op EN))
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 eachEi
is generated by instantiating the pattern and replacing each pack expansion parameter with itsi
th element. [...]
Therefore, (enums >>= ...)
is semantically equivalent to (A >>= (B >>= C))
when you instantiate it. So this is a bug in Clang.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With