Vim + OmniCppComplete: завершение для членов класса, которые являются контейнерами STL - PullRequest
11 голосов
/ 16 мая 2010

Завершение для членов класса, которые являются контейнерами STL, терпит неудачу.

Завершение на локальных объектах, которые являются контейнерами STL, работает нормально.

Например, с учетом следующих файлов:

// foo.h
#include <string>

class foo {
public:
    void set_str(const std::string &);

    std::string get_str_reverse( void );

private:
    std::string str;
};

// foo.cpp
#include "foo.h"

using std::string;

string
foo::get_str_reverse ( void )
{
    string temp;

    temp.assign(str);
    reverse(temp.begin(), temp.end());

    return temp;
}       /* -----  end of method foo::get_str  ----- */

void
foo::set_str ( const string &s )
{
    str.assign(s);
}       /* -----  end of method foo::set_str  ----- */

Я сгенерировал теги для этих двух файлов, используя:

ctags -R --c++-kinds=+pl --fields=+iaS --extra=+q .

Когда я набираю temp. в cpp, я получаю список string функций-членов, как и ожидалось. Но если я наберу str. omnicppcomplete выплюнет "Pattern Not Found".

Я заметил, что завершение temp. работает, только если у меня есть объявление using std::string;.

Как получить завершение работы над учениками, которые являются контейнерами STL?

Редактировать

Я обнаружил, что завершение для элементов, являющихся контейнерами STL, работает, если я внесу следующие изменения в заголовок:

// foo.h
#include <string>

using std::string;

class foo {
public:
    void set_str(const string &);

    string get_str_reverse( void );

private:
    string str;
};

Обычно, если я добавлю using std::string;, а затем удалю спецификатор пространства имен std:: из элемента string str; и заново создаю файл тегов, OmniCppComplete сможет выполнить завершение str..

Не имеет значения, установлен ли у меня let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"] в .vimrc.

Проблема в том, что размещение using объявлений в заголовочных файлах кажется большим «нет-нет», поэтому я вернулся к исходной точке.

Ответы [ 2 ]

1 голос
/ 23 мая 2010

Я недавно перешел на Ubuntu 10.04, который включает в себя ctags 5.8, и у меня больше нет этой проблемы с классами STL, такими как string, однако завершение все еще не работает с реальными контейнерами, такими как vector.

Это мой старый ответ на ctags 5.7:

Хотя это немного хакерское решение, я нашел решение, которое не загрязняет заголовочные файлы директивами using и обеспечивает OmniCppComplete всем необходимым для выполнения членов класса, являющихся контейнерами STL.

#include <string>

#if 0
using std::string;
#else
#   define string std::string
#endif

class foo {
public:
    void set_str(const string &);

    string get_str_reverse( void );

private:
    string str;
};

#ifdef string
#   undef string
#endif

Затем измените строку в файле .vimrc, которая генерирует ctags, следующим образом:

map <C-F12> :!ctags -R --c++-kinds=+pl --fields=+iaS --extra=+q --if0=yes .<CR>

Как это работает? Когда ctags видит параметр --if0=yes, он принимает ветвь #if 0 директивы препроцессора и генерирует необходимую запись в файле tags:

str omnitest.h  /^    string str;$/;"   m   class:foo   access:private

OmniCppComplete видит подделку using std::string;, а когда не может найти определение для string, он смотрит в пространство имен std и находит его там.

А при компиляции с g ++ вывод - это то, что мы хотим. Это можно проверить, запустив файлы через препроцессор:

$ g++ omnitest.cpp -E | less

В конце вы увидите:

# 2 "omnitest.h" 2

class foo {
public:
    void set_str(const std::string &);

    std::string get_str_reverse( void );

private:
    std::string str;
};
# 2 "omnitest.cpp" 2

using std::string;

string foo::get_str_reverse ( void )
{
    string temp;

    temp.assign(str);
    reverse(temp.begin(), temp.end());

    return temp;
}

void foo::set_str ( const string &s )
{
    str.assign(s);
}

Так, например, если я наберу this->str. в одной из функций-членов, она теперь выдаст мне список строковых членов для завершения.

Этот метод может использоваться для любого набора контейнеров STL и даже может быть автоматизирован для изменения заголовка при регистрации или извлечении из хранилища Subversion с использованием сценария Perl.

Таким образом, ваши товарищи по команде не должны видеть ваши уродливые хаки: -)

0 голосов
/ 18 мая 2010

Попробуйте установить эту переменную:

let OmniCpp_NamespaceSearch=1

Если это работает, не забудьте поместить его в файл конфигурации .vimrc!

...