Knowing Where and why do we have to put the template
and typename
keywords, I was surprised to learn that MSVC accepts the following code:
struct foo {
using bar = int;
};
template <typename T>
void quux() {
T::template bar b;
}
int main() {
quux<foo>();
}
From my understanding, the usage of T::template bar b;
is incorrect. The correct way to declare b
would be to use typename
, like so: typename T::bar b;
(instead of T::template bar b;
). template
would imply that bar
is a, well, a template, which is not the case.
Is it a bug in MSVC resulting in it accepting incorrect code, or is it permitted by the standard and simply both Clang and GCC don't implement it that way (thus requiring the proper usage of typename
here)?
MSVC has a long-standing bug - it was already an old bug when I asked that template-typename question which you linked. In short, C++ since 1998 requires Two-Phase Name Lookup in templates. In the first phase, when the template itself is compiled, only the names which are not dependent are looked up, as the actual template arguments are not yet known. In the second phase, dependent names are looked up (for details, see the linked question).
But MSVC doesn't do this, and does all lookup when instantiating the template. In your case, that means all the lookup is done when MSVC compiles quux<foo>
, and nothing when compiling quux<T>
. And since it doesn't do the first phase, it doesn't need that typename
on a dependent name. MSVC already knows about quux::b
.
It appears that MSVC goes a bit further. Not only does it ignore the correct typename
, but it also ignores incorrect use of template
as in this example. That's not entirely surprising when ignoring things.
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