2010-05-16 10 views
11

L'achèvement sur les membres de la classe qui sont des conteneurs STL échoue. L'achèvement sur les objets locaux qui sont des conteneurs STL fonctionne correctement.Vim + OmniCppComplete: achèvement sur les membres de la classe qui sont des conteneurs STL

Par exemple, étant donné les fichiers suivants:

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

J'ai produit les balises pour ces deux fichiers à l'aide:

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

Lorsque je tape temp. dans le cpp je reçois une liste de string Le membre fonctionne comme prévu. Mais si je tape str. omnicppcomplete crache "Pattern Not Found".

J'ai remarqué que la complétion temp. ne fonctionne que si j'ai la déclaration using std::string;.

Comment puis-je obtenir l'achèvement de travailler sur mes membres de classe qui sont des conteneurs STL?

Modifier

J'ai trouvé que l'achèvement des membres qui sont des conteneurs STL fonctionne si je fais les modifications de suivi à l'en-tête:

// foo.h 
#include <string> 

using std::string; 

class foo { 
public: 
    void set_str(const string &); 

    string get_str_reverse(void); 

private: 
    string str; 
}; 

En gros, si j'ajoute using std::string; puis retirez le std:: nommez le qualificatif d'espace du membre string str; et régénérez le fichier de balises, puis OmniCppComplete est en mesure d'effectuer l'achèvement sur str..

Il ne semble pas important si oui ou non j'ai let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"] dans le .vimrc.

Le problème est que mettre des déclarations using dans les fichiers d'en-tête semble être un gros non-non, donc je suis de retour à la case départ.

+0

drôle: J'ai essayé votre test et pour moi, c'est exactement le contraire! str fonctionne et temp ne ... quelle version de ctags utilisez-vous d'ailleurs? – UncleZeiv

+0

en fait la température fonctionne aussi si je fais ': laissez OmniCpp_DefaultNamespaces = [" std "]' – UncleZeiv

+0

@UncleZeiv: J'utilise ctags 5.7 sur Ubuntu 8.04. J'ai trouvé que cela n'a pas d'importance si j'ai Default_Namespaces. Voir ma modification ci-dessus. –

Répondre

0

Essayez définition de cette variable:

let OmniCpp_NamespaceSearch=1 

Si cela fonctionne, ne pas oublier de mettre dans votre fichier de configuration .vimrc!

+0

Je l'avais déjà allumé et ça ne fait aucune différence. –

+0

J'ai trouvé une solution si vous êtes intéressé. –

+0

Pouvez-vous poster ici? –

1

Je me suis récemment déplacé vers Ubuntu 10.04, qui inclut ctags 5.8 et je n'ai plus ce problème avec les classes STL comme string, cependant l'achèvement ne fonctionne toujours pas avec des conteneurs réels comme vector.

Ceci est ma réponse ancienne pour ctags 5.7:

Bien qu'il soit un peu un hack, j'ai trouvé une solution qui ne pollue pas les fichiers d'en-tête avec using directives et fournit OmniCppComplete avec tout ce qu'il doit compléter les membres de classe qui sont des conteneurs 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 

la ligne Modifiez ensuite dans le fichier .vimrc qui génère les ctags comme suit:

map <C-F12> :!ctags -R --c++-kinds=+pl --fields=+iaS --extra=+q --if0=yes .<CR> 

Comment ça marche? Lorsque ctags voit l'option --if0=yes il prendra la branche #if 0 de la directive préprocesseur et génère l'entrée nécessaire dans le fichier tags:

str omnitest.h /^ string str;$/;" m class:foo access:private 

OmniCppComplete voit le using std::string; faux et quand il ne peut pas trouver une définition pour string il regarde dans l'espace de noms std et le trouve là.

Et lors de la compilation avec g ++, la sortie est ce que nous voulons. Cela peut être vérifié en exécutant les fichiers via le préprocesseur:

$ g++ omnitest.cpp -E | less 

A la fin, vous verrez:

# 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); 
} 

Ainsi, par exemple, si je tape this->str. dans l'une des fonctions membres il maintenant me donne une liste de membres à compléter.

Cette technique peut être utilisée pour n'importe quel ensemble de conteneurs STL et peut même être automatisée pour modifier l'en-tête lors de l'archivage ou de la sortie d'un référentiel Subversion à l'aide d'un script Perl.

De cette façon, vos coéquipiers ne ont pas besoin de voir vos hacks laids :-)

+0

bien ... c'est vraiment un hack terrible! :) J'utilise souvent #if 0 pour commenter des choses, donc je n'utiliserais pas cette définition particulière. En dehors de ça, je suis content que vous ayez trouvé une solution qui vous convient, mais je me demande encore pourquoi je ne peux pas reproduire votre bug ... si j'ai d'autres idées de ce qui pourrait être mauvais dans votre environnement, je vous le ferai savoir :) – UncleZeiv