I have the following function defined in a header file (the library it is part of aims at being header-only):
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 ...
}
I am trying to compile a small simple program that includes this file but I get undefined references to all the lambdas at link time. When I say simple there's a single CPP that compiles but can't link. Here the first error:
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&)'
It's happening since I have upgraded to GCC 4.7.2, it used to work fine in GCC 4.6.2 (Ubuntu versions in case that helps). While I know workarounds to solve the problem, I am wondering what I am doing wrong or not understand properly. Since the lambas are inside the inline function they should be defined in any translation unit that uses that function.
-- EDIT --
One more thing worth noting: the Search
and GetComparer
function are not used in the sample program.
Search
is used in a member function of Table<Description>
(I can't post the full class):
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);
}
But neither are called from the sample.cpp file. That file test other features of Table
which are unrelated. If I comment the call in the member, the code compiles and links. (I need the member function, it's virtual, it's part of a type erasure class above Table
).
main
program that callsGetComparer
. The error disappears if I use a function object, rather than a function pointer:tyepdef std::function<bool(const std::string&, const std::string&)> FieldComparer;
. – Nikoinline
? That seems to fix the problem on the liveworkspace link. Still, looks like you've found a compiler bug. – Narwhalinline
is required. That library was meant to be header only ... I'll see if it's worth changing or not ;) – Baresark