Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda not found when defined in an inline function in G++ 4.7

Tags:

c++

c++11

gcc4.7

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

like image 619
J.N. Avatar asked Oct 22 '12 01:10

J.N.


1 Answers

A bug report has been filed with the GCC team, and one of the developers has confirmed the issue on trunk.

In the mean time, as LucDanton pointed out in chat, declaring the function static will solve the problem.

like image 178
nneonneo Avatar answered Nov 10 '22 13:11

nneonneo