В проекте, расширяющем библиотеку boost.intrusive, который я недавно рассмотрел, я обнаружил в классе следующий код treap_impl
:
node_ptr this_head(this->tree_type::header_ptr());
node_ptr right(this->tree_type::node_algorithms::root_node(this_head));
Рассматриваемый код компилируется в MSVC 17.9, но не использует clang или gcc из-за ошибки во второй строке:
...::node_algorithms is not a base of treap_impl<...>
Удаление this->
из второй строки устраняет ошибку.
Мои вопросы:
this->tree_type
, стандарту C++?Вот пример, который воспроизводит одну и ту же ошибку в gcc и clang. Это также не удается скомпилировать с MSVC в проводнике компилятора. К сожалению, я не уверен, как воспроизвести точную настройку, описанную выше, то есть, что необходимо для компиляции с MSVC, но не с 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());
}
};
Рассматриваемая ошибка:
error: ‘A::the_type’ {aka ‘static_thing’} is not a base of ‘B’
«К сожалению, я не уверен, как точно воспроизвести описанную выше настройку». Вы можете добавить библиотеку boost
и включить необходимые заголовки даже в Compiler Explorer.
this->a_type::the_type::value()
говорит: «Найдите метод или вызываемый член с именем value
в базовом классе a_type::the_type
и вызовите его». Его можно вызывать как вызываемый объект, как метод со скрытым аргументом this
или как метод static
, но в любом случае для поиска доступны только члены и методы-члены.
В отличие от одного a_type::the_type::value()
, который в этом контексте также мог означать то же самое, но также имел другую перегрузку: «найти функцию или вызываемую переменную с именем value
в пространстве имен a_type::the_type
и вызвать ее без аргументов». Список членов базового класса по-прежнему имеет приоритет в качестве пространства имен для поиска, но вы больше не ограничены только базовыми классами.
Что касается того, что понял/хотел компилятор:
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());
}
};
Применительно к вашему исходному вопросу класс treap_impl
должен был унаследовать от класса node_algorithms
, чтобы получить доступ к признакам, определенным в этом классе.
Когда вы сказали
this->tree_type::node_algorithms::root_node(this_head)
, вы пытались сказать «вызватьroot_node(this_head)
из пространства именtree_type::node_algorithms
»? Если да, то это не метод, а отдельная функция. Вы можете вызывать методы без явногоthis->
, но не можете вызывать функции как метод. Методы принадлежат объекту и нуждаются в объекте в качестве контекста, функции являются автономными и не имеют контекста.