Considering the following code example, I would expect to have to use the template keyword here to guide the compiler to treat variable v as a template. However, MSVC rejects the use of the template keyword, whereas Clang and GCC actually require it. Which specific rule in the C++20 standard either mandates or forbids the use of the template keyword in this case?
struct s {
template<typename...>
static constexpr auto v = true;
};
// all ok
static_assert([](auto x){ return decltype(x)::template v<>; }(s{}));
// clang ok, gcc ok, msvc nope
static_assert([](auto x){ return x.template v<>; }(s{}));
// clang nope, gcc nope, msvc ok
static_assert([](auto x){ return x.v<>; }(s{}));
The error message from Clang:
<source>:10:36: error: use 'template' keyword to treat 'v'
as a dependent template name
10 | static_assert([](auto x){ return x.v<>; }(s{}));
| ^
| template
The error message from MSVC:
<source>(8): error C2187: syntax error: 'template' was unexpected here
<source>(8): note: see reference to function template instantiation
'auto <lambda_2>::operator ()<s>(_T1) const' being compiled
with
[
_T1=s
]
In short,
xanddecltype(x)are dependent, andtemplateis allowed and necessary in all cases. There is an MSVC compiler bug.C++ standard wording
As for dependent types, including
decltype:- [temp.dep.type] p7.10
Furthermore,
xis type-dependent because (see [temp.dep.expr] p3.1) it is:The
autoparameter for the generic lambda makes the call operator a function template, so naturally,xis associated with a template parameter, which is dependent. Thereforetemplateis necessary fordecltype(x)::template v<>. All compilers agree and this is correct.In the statement
xis type-dependent because it is associated by name lookup with an implicit template parameter of the generic lambda's call operator. Therefore,templateis necessary.Note: Besides the standardese, it's intuitively necessary because
x.v <could be interpreted as "x.vis less than ..." if it isn't known thatvis a template. This is formally stated in [temp.names] p3.See also: Where and why do I have to put the "template" and "typename" keywords?
MSVC compiler bug
The fact that MSVC doesn't allow
.template v<>is obviously a bug. It's worth noting that MSVC does accept:However, using
autoinstead ofsas the parameter type leads to a compiler error. This makes no sense at all, sincetemplateandtypenameare optional and adding them unnecessarily should never cause failure.Note: I was unable to find an existing bug report in the Microsoft Developer Community, so maybe this hasn't been reported yet. You may want to report this bug.