Проблема с кодом в Netbeans 8.2 с unique_ptr (не shared_ptr) - PullRequest
0 голосов
/ 02 апреля 2020

При использовании Netbeans 8.2 на Linux и G CC 8.1, unique_ptr::operator->() выдает ошибочное предупреждение Unable to resolve template based identifier {var} и, что более важно, не будет автозаполнять имена членов.

Код компилируется и выполняется просто отлично, и Удивительно, но автозаполнение все еще работает без предупреждений, если вместо используется shared_ptr. Я понятия не имею, как это возможно. Вот проблемный c пример, для справки

#include <iostream>
#include <memory>

struct C { int a;};

int main () {
  std::unique_ptr<C> foo (new C);
  std::shared_ptr<C> bar (new C);

  foo->a = 10; //Displays warning, does not auto-complete the members of C
  bar->a = 20; //No warning, auto-completes members of C

  return 0;
}

Я попытался решить эту проблему без удачи:

  1. Помощь по коду> Повторная обработка проекта
  2. Поддержка кода> Очистка кеша C / C ++ и перезапуск IDE
  3. Удаление кеша вручную в ~/.cache/netbeans/8.2
  4. Просмотр View> IDE Log для всего, что может помочь
  5. Установка для компиляторов C и C ++ значения C11 и C ++ 11 в свойствах проекта
  6. Изменение макроса предварительной обработки __cplusplus на 201103L и 201402L
  7. Создание нового проекта Netbeans и пробуя вышеописанное
  8. Большое разнообразие вариантов вышеуказанных опций в разных порядках

Опять же, все компилируется и работает просто отлично, только Code Assistance вызывает у меня проблему. Я исчерпал вещи, которые я нашел в других ответах переполнения стека. Моя интуиция подсказывает мне, что shared_ptr работает и unique_ptr не работает полезно, но я недостаточно знаю C ++, чтобы использовать эту информацию. Пожалуйста, помогите мне, мне нужно вернуться к работе ...

Изменить 1

Этот вопрос переполнения стека , хотя ссылается на Clang и Реализация libc ++ предполагает, что это может быть проблемой реализации в libstdc ++ unique_ptr.

в G CC 8.1.

1 Ответ

0 голосов
/ 03 апреля 2020

Метод TLDR 1

Добавление директивы using pointer = {structName}* в вашу структуру исправляет помощь кода и будет компилироваться и запускаться, как и предполагалось, например:

struct C { using pointer = C*; int a;};

Метод TLDR 2

Ответ , на который я ссылаюсь в моем редактировании, фактически работает и для libstdc ++. Простое изменение типа возврата unique_ptr::operator->() с pointer на element_type* исправит помощь кода, скомпилирует и запустит, как и ожидалось (то же самое можно сделать с unique_ptr::get()). Тем не менее, меняются вещи в реализациях стандартной библиотеки.

Дополнительная информация

Как человек, который является относительно новым для c ++ и едва понимает силу специализаций шаблонов. чтение через unique_ptr.h было страшным, но вот что, мне кажется, портит Netbeans:

  1. вызов unique_ptr::operator->() вызовов unique_ptr::get()
  2. unique_ptr::get() вызывает частную реализацию (__unique_ptr_impl) функция указателя __unique_ptr_impl::_M_ptr(). Все эти вызовы возвращают тип __unique_ptr_impl::pointer.
  3. В частной реализации тип pointer определен в еще более частной реализации _Ptr. Структура _Ptr имеет два определения шаблона, одно из которых возвращает необработанный указатель на начальную переменную шаблона unique_ptr, а второе, кажется, удаляет любую ссылку из этой переменной шаблона, а затем находит ее тип с именем pointer. Я думаю, что это где Netbeans портится.

Итак, насколько я понимаю, когда вы вызываете unique_ptr<elementType, deleterType>::operator->(), он переходит к __unique_ptr_impl<elementType, deleterType>, где внутренний тип указателя определяется путем удаления elementType любых ссылок и последующего получения типа с именем dereferenced(elementType)::pointer. Таким образом, включив директиву using pointer =, Netbeans получает то, что хочет, при поиске типа dereferenced(elementType)::pointer.

Включение директивы using совершенно поверхностно, о чем свидетельствует тот факт, что вещи будут компилироваться без него, и в следующем примере

#include <memory>
#include <iostream>
struct A{
  using pointer = A*; 
  double memA; 
  A() : memA(1) {}
};
struct B {
  using pointer = A*; 
  double memB; 
  B() : memB(2) {}
};
int main() {
  unique_ptr<A> pa(new A);
  unique_ptr<B> pb(new B);
  std::cout << pa->memA << std::endl;
  std::cout << pb->memB << std::endl;
};

выводит

1
2

Как и должно быть, хотя в структуре B содержится using pointer = A*. Netbeans на самом деле пытается автозаполнить B-> до B->memA, что является еще одним доказательством того, что Netbeans использует предложенную выше логику c.

Это решение придумано как ад, но по крайней мере работает (в c контекст, который я использовал) без внесения изменений в реализации stl. Кто знает, я все еще запутался в запутанной системе ввода в unique_ptr.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...