In a project extending the boost.intrusive library I recently reviewed I encountered the following code in the class treap_impl
:
node_ptr this_head(this->tree_type::header_ptr());
node_ptr right(this->tree_type::node_algorithms::root_node(this_head));
The code in question compiles on MSVC 17.9, but not using clang or gcc, due to an error on the second line:
...::node_algorithms is not a base of treap_impl<...>
Removing this->
from the second line resolves the error.
My questions:
this->tree_type
part, comply with the C++ standard?Here is an example that reproduces the same error on gcc and clang. This also fails to compile with MSVC on compiler explorer. Sadly I'm not sure how to reproduce the exact setting described above, i.e., what's needed to make it compile with MSVC, but not with gcc/clang.
struct static_thing {
static int value() {
return 5;
}
};
struct A {
using the_type = static_thing;
};
class B {
using a_type = A;
void do_stuff() {
int a(this->a_type::the_type::value());
}
};
The error in question:
error: ‘A::the_type’ {aka ‘static_thing’} is not a base of ‘B’
this->a_type::the_type::value()
says "find a method or callable member called value
on the base class a_type::the_type
and call it". It may be called as a callable, as a method with a hidden this
argument or as a static
method, but in any case only members and member methods are eligible for the lookup.
That's unlike a_type::the_type::value()
alone, which in that context could also have meant the same, but also had the other overload of "find a function or callable variable called value
in the namespace a_type::the_type
and call it without arguments". The list of base class members still has precedence as the namespace for the lookup, but you are no longer constrained to base classes alone.
As for what the compiler understood / wanted:
struct static_thing {
static int value() {
return 5;
}
};
struct A {
using the_type = static_thing;
};
// There is now value() from static_thing as a member on B
// static_thing is additionally known by the alias a_type::the_type
class B : public static_thing {
using a_type = A;
void do_stuff() {
int a(this->a_type::the_type::value());
}
};
Applied to your original question, the class treap_impl
should have inherited from the class node_algorithms
in order to gain access to the traits defined in that class.