31 votes

Lambda non trouvé lorsqu'il est défini dans une fonction inline dans G++ 4.7

J'ai la fonction suivante définie dans un fichier d'en-tête (la bibliothèque dont elle fait partie a pour but de n'être qu'un en-tête) :

typedef bool (*FieldComparer)(const std::string&, const std::string&);

inline FieldComparer
GetComparer(const std::string& query, string& separator)
{
    if (query.find('=') != std::string::npos) {
        separator = "=";
        return [](const string& s1, const string& s2) { return s1 == s2; };
    }
    else if (query.find('^') != string::npos) {
        separator = "^";
        return [](const string& s1, const string& s2) { return boost::starts_with(s1, s2); };
    }
    else if (query.find('*') != string::npos) {
        separator = "*";
        return [](const string& s1, const string& s2) { return boost::contains(s1, s2); };
    }
    else if (query.find('!') != string::npos) {
        separator = "!";
        return [](const string& s1, const string& s2) { return s1 != s2; };
    }
    else
        throw std::invalid_argument("Search: could not find operator in query string.");
}

template <class Description>
inline void
Search(Table<Description>& table, const std::string& query,
        std::function<void(const std::string&)> callback, int begin, int limit)
{
    string separator;
    auto comparer = GetComparer(query, separator);

    ... do stuff with comparer ...
}

J'essaie de compiler un petit programme simple qui inclut ce fichier mais j'obtiens des références indéfinies à tous les lambdas au moment de la liaison. Quand je dis simple, il y a un seul CPP qui compile mais ne peut pas lier. Voici la première erreur :

obj/sample.o: In function `DataModel::GetComparer(std::string const&, std::string&)::{lambda(std::string const&, std::string const&)#1}::operator bool (*)(std::string const&, std::string const&)() const':
/home/julien/workspace_dma/src/DataModel/Search.h:23: undefined reference to `DataModel::GetComparer(std::string const&, std::string&)::{lambda(std::string const&, std::string const&)#1}::_FUN(std::string const&, std::string const&)'

Cela se produit depuis que j'ai mis à jour vers GCC 4.7.2, cela fonctionnait bien dans GCC 4.6.2 (versions Ubuntu au cas où cela aiderait). Bien que je connaisse des solutions de contournement pour résoudre le problème, je me demande ce que je fais mal ou ce que je ne comprends pas correctement. Puisque les lambas sont à l'intérieur de la fonction en ligne, ils devraient être définis dans toute unité de traduction qui utilise cette fonction.

-- EDIT --

Une autre chose à noter : le Search et GetComparer ne sont pas utilisés dans le programme d'exemple.

Search est utilisé dans une fonction membre de Table<Description> (Je ne peux pas afficher la classe complète) :

template <class Description>
void Table<Description>::Search(const std::string& query,
        std::function<void(const std::string&)> callback, int begin, int count)
{
    DataModel::Search(*this, query, callback, begin, count);
}

Mais aucun des deux n'est appelé depuis le fichier sample.cpp. Ce fichier teste d'autres fonctionnalités de Table qui n'ont aucun rapport. Si je commente l'appel dans le membre, le code se compile et se lie. (J'ai besoin de la fonction membre, elle est virtuelle, elle fait partie d'une classe d'effacement de type ci-dessus). Table ).

5voto

nneonneo Points 56821

A rapport de bogue a été déposé auprès de l'équipe GCC, et l'un des développeurs a confirmé le problème sur le tronc .

En attendant, comme LucDanton l'a fait remarquer dans le chat, déclarer la fonction static résoudra le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X