views:

279

answers:

2

Completion on class members which are STL containers is failing.

Completion 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.

A: 

Try setting this variable:

let OmniCpp_NamespaceSearch=1

If it works, don't forget to put it in your .vimrc configuration file!

UncleZeiv
I already had that turned on and it doesn't make any difference.
Robert S. Barnes
I found a solution if you're interested.
Robert S. Barnes
+1  A: 

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 :-)

Robert S. Barnes
well... it really is a terrible hack! :) I often use #if 0 to comment out stuff so I wouldn't use that particular define. Other than that, I'm glad you found a solution that suits you, but I still wonder why I can't reproduce your bug... if I have other ideas of what could be wrong in your environment I'll let you know :)
UncleZeiv