11

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  ----- */

以下を使用して、これら 2 つのファイルのタグを生成しました。

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

temp.cpp を入力するとstring、期待どおりにメンバー関数のリストが表示されます。しかし、str.omnicppcomplete と入力すると、「パターンが見つかりません」というメッセージが表示されます。

宣言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;削除し、タグ ファイルを再生成すると、OmniCppComplete は で補完を行うことができます。std::string str;str.

let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]に設定したかどうかは問題ではないようです.vimrc

問題はusing、ヘッダー ファイルに宣言を配置することは大したことではないように思えることです。そのため、振り出しに戻ります。

4

2 に答える 2

1

最近、ctags 5.8 を含む Ubuntu 10.04 に移行しましたが、文字列などの STL クラスでこの問題は発生しなくなりましたが、補完はベクトルなどの実際のコンテナーではまだ機能しません。

これは、ctags 5.7 に対する私の古い回答です。

ちょっとしたハックですが、ヘッダー ファイルをusingディレクティブで汚染せず、STL コンテナーであるクラス メンバーを完成させるために必要なすべてのものを OmniCppComplete に提供するソリューションを見つけました。

#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.メンバー関数の 1 つを入力すると、文字列メンバーのリストが表示されます。

この手法は、STL コンテナーの任意のセットに使用でき、Perl スクリプトを使用して Subversion リポジトリーのチェックインまたはチェックアウト時にヘッダーを変更するように自動化することもできます。

そうすれば、チームメイトはあなたの醜いハックを見る必要がありません:-)

于 2010-05-23T14:10:11.257 に答える
0

この変数を設定してみてください:

let OmniCpp_NamespaceSearch=1

.vimrc動作する場合は、構成ファイルに入れることを忘れないでください!

于 2010-05-18T14:36:16.107 に答える