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