struct data_t
{
template<class T>
auto foo(T t)
{
t + "";
}
};
template<class ...Ts>
void bar(Ts&&...)
{}
template<class T>
auto bar(T h)->decltype(h.invalid, h.foo(&h))
{}
void test_bar()
{
data_t h;
bar(h);
}
The above mentioned codes are accepted by clang 10+ (ref: https://godbolt.org/z/MM7habqY1) but rejected by gcc 10+ (ref: https://godbolt.org/z/5W6Gv6Wqx ), regarding c++14/17/20 standard.
Obviously, clang skips further parsing when finding h.invalid, and then SFINAR kicks in. However gcc tries to look into both operands of comma operator, which causing a hard error because of instantiating a function template with error.
C++20 standard said in $13.10.3.1 (Template argument deduction):
The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered
Also we know that for built-in expression (E1, E2), E1 is sequenced before E2.
My best bet is that clang is correct. The key point is lexical order and/or sequenced before.
My question is: Which one conforms c++ standard regarding this corner case in SFINAE relevant to unevaluated expression?