C++ Vim+;OmniCppComplete:在STL容器类成员上完成

C++ Vim+;OmniCppComplete:在STL容器类成员上完成,c++,linux,vim,ctags,omnicomplete,C++,Linux,Vim,Ctags,Omnicomplete,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" u

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  ----- */
当我在cpp中键入
temp.
时,我会得到一个
string
成员函数的列表。但如果我键入
str.
omnicpmplete,则会弹出“找不到模式”

我注意到,只有当我使用std::string时,
temp.
完成才有效声明

我如何完成对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;
};
//foo.h
#包括
使用std::string;
福班{
公众:
空集_str(常量字符串&);
字符串get_str_reverse(void);
私人:
字符串str;
};
基本上,如果我使用std::string添加
然后从
字符串str中删除
std::
名称空间限定符成员并重新生成标记文件,然后OmnicpComplete可以在
str.
上完成

我是否在
.vimrc
中设置了
让OmniCpp\u DefaultNamespaces=[“std”,“\u GLIBCXX\u std”]
似乎并不重要


问题是,在头文件中使用
声明似乎是一个很大的禁忌,因此我回到了原点。

尝试设置此变量:

let OmniCpp_NamespaceSearch=1

如果它能工作,别忘了把它放在
.vimrc
配置文件中

我最近搬到了Ubuntu 10.04,其中包括ctags 5.8,我不再有像string这样的STL类的问题,但是完成仍然不能工作像vector这样的实际容器

这是我对ctags 5.7的旧答案:

虽然这有点像黑客,但我已经找到了一种解决方案,它不会使用
指令污染
头文件,并提供OmnicpComplete完成类成员(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
这是怎么回事?当
ctags
看到
--if0=yes
选项时,它将采用预处理器指令的
#if 0
分支,并在
标记
文件中生成必要的条目:

str omnitest.h  /^    string str;$/;"   m   class:foo   access:private
OmniCppComplete使用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容器,甚至可以在使用Perl脚本签入或签出Subversion存储库时自动修改头


这样,你的队友就不需要看到你丑陋的黑客:-)

有趣的是:我试过你的测试,对我来说正好相反!str工作,temp不工作。。。顺便问一下,您使用的是哪个版本的ctags?如果我使用的话,实际上temp也可以工作
:让OmniCpp_DefaultNamespaces=[“std”]
@Uncleziv:我在Ubuntu 8.04上使用的是ctags 5.7。我发现是否设置了默认的_名称空间似乎并不重要。请参阅我上面的编辑。我认为建议使用ctags 5.8,尝试编译它或从以后的Ubuntus获得一个包(不应该有任何令人讨厌的依赖)。我已经打开了它,它没有任何区别。如果您感兴趣,我找到了一个解决方案。嗯。。。这真是一个可怕的黑客行为!:)我经常使用#if 0来注释内容,所以我不会使用那个特定的定义。除此之外,我很高兴你找到了一个适合你的解决方案,但我仍然想知道为什么我不能复制你的错误。。。如果我对您的环境中可能出现的问题有其他想法,我会让您知道:)
$ 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);
}