This question is a follow up of
Moving a member function from base class to derived class breaks the program for no obvious reason (this is a prime example of why one shouldn't use using namespace std;
)
where the answers suggested qualifying by this->
a dependent template name (which indeed is the way to go when referring to such dependent members). However, there seems to be an issue, so I'll list a minimal example that reproduces the problem.
Consider the code:
#include <iostream>
#include <bitset>
using namespace std;
template<class T>
struct B
{
T bitset{};
};
template<class T>
struct D : B<T>
{
bool foo()
{
return this->bitset < 32;
}
};
int main(){}
The perplexing thing is that even though this->bitset
should refer to the member B<T>::bitset
, the compiler is still confused and believes that we try to refer to std::bitset<std::size_t>
. The error appears on both gcc6 and clang3.7. Any ideas why this happens? Qualifying it with B<T>::bitset
works though.
Error (verbatim):
In member function 'bool D<T>::foo(T, std::__cxx11::string)': cpp/scratch/minimal.cpp:24:22: error: invalid use of 'class std::bitset<1ul>'
EDIT
This looks to me like a parsing/name lookup bug. If we replace <
by any other comparison operator (thanks @Leon for the remark), e.g.
return this->bitset == 32;
the program compiles. So I guess in this->bitset < 32
the parser believes that we are trying to instantiate a template (the <
sign), and we forgot to close the >
. But again have no idea if this is indeed a bug or that's how the language is suppose to work.
tl;dr it looks like this is a deliberate decision, specifically to support the alternate syntax you already used.
An approximate walkthrough of the standardese below:
this->B
does name something, but it's a templateB<T>
, so keep goingB
on it's own also names something, a class templateB<T>
this->B<T>
as a qualifier, and it isn't a less-than after allIn the other case,
proceeds identically until the third step, when it realises there are two different things called
bitset
(a template class member and a class template), and just gives up.This is from a working draft I have lying around, so not necessarily the most recent, but:
So, in any expression like
this->id < ...
, it has to handle cases whereid<...
is the start of a template identifier (likethis->B<T>::bitset
).It still checks the object first, but if
this->id
finds a template, further steps apply. And in your case,this->bitset
is presumably considered a template as it still depends onT
, so it finds the conflictingstd::bitset
and fails at the third bullet above.