Vim + OmniCppComplete: завершение на членах класса, которые являются контейнерами STL

Выполняется завершение работы над членами класса, которые являются контейнерами 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?

Edit

Я обнаружил, что завершение элементов, которые являются контейнерами 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 в заголовочных файлах кажется большим нет-нет, поэтому я вернусь к квадрату.

Ответ 1

Недавно я перешел в Ubuntu 10.04, в который входит ctags 5.8, и у меня больше нет этой проблемы с классами STL, например с строкой, однако завершение по-прежнему не работает с фактическими контейнерами, такими как вектор.

Это мой старый ответ для 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 script.

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

Ответ 2

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

let OmniCpp_NamespaceSearch=1

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