Vim + OmniCppComplete: Completing on Class Members which are STL containers
Completion on class members which are STL containers is failing.
Comp开发者_运维问答letion on local objects which are STL containers works fine.
For example, given the following files:
// 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 ----- */
I've generated the tags for these two files using:
ctags -R --c++-kinds=+pl --fields=+iaS --extra=+q .
When I type temp.
in the cpp I get a list of string
member functions as expected. But if I type str.
omnicppcomplete spits out "Pattern Not Found".
I've noticed that the temp.
completion only works if I have the using std::string;
declaration.
How do I get completion to work on my class members which are STL containers?
Edit
I found that completion on members which are STL containers works if I make the follow modifications to the header:
// foo.h
#include <string>
using std::string;
class foo {
public:
void set_str(const string &);
string get_str_reverse( void );
private:
string str;
};
Basically, if I add using std::string;
and then remove the std::
name space qualifier from the string str;
member and regenerate the tags file then OmniCppComplete is able to do completion on str.
.
It doesn't seem to matter whether or not I have let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]
set in the .vimrc
.
The problem is that putting using
declarations in header files seems like a big no-no, so I'm back to square one.
I moved recently to Ubuntu 10.04, which includes ctags 5.8 and I no longer have this problem with STL classes like string, however completion still doesn't work actual containers like vector.
This is my old answer for ctags 5.7:
While it's a bit of a hack, I've found a solution which doesn't pollute the header files with using
directives and provides OmniCppComplete with everything it needs to complete class members which are STL containers.
#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
Then modify the line in the .vimrc
file which generates the ctags as follows:
map <C-F12> :!ctags -R --c++-kinds=+pl --fields=+iaS --extra=+q --if0=yes .<CR>
How does this work? When ctags
sees the --if0=yes
option it will take the #if 0
branch of the preprocessor directive and generates the necessary entry in the tags
file:
str omnitest.h /^ string str;$/;" m class:foo access:private
OmniCppComplete sees the fake using std::string;
and when it can't find a definition for string
it looks in the std
namespace and finds it there.
And when compiling with g++ the output is what we want. This can be verified by running the files through the preprocessor:
$ g++ omnitest.cpp -E | less
At the end you'll see:
# 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);
}
So for example, if I type this->str.
in one of the member functions it now gives me a list of string members to complete from.
This technique can be used for any set of STL containers and could even be automated to modify the header on check in or check out from a Subversion repository using a Perl script.
That way your team mates don't need to see your ugly hacks :-)
Try setting this variable:
let OmniCpp_NamespaceSearch=1
If it works, don't forget to put it in your .vimrc
configuration file!
精彩评论