Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does MSVC incorrectly treat template keyword in dependent names?

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)?

like image 772
Fureeish Avatar asked Nov 15 '22 19:11

Fureeish


1 Answers

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.

like image 186
MSalters Avatar answered Dec 30 '22 17:12

MSalters