ヘッダーファイルで次の関数を定義しています(ヘッダーのみを目的としたライブラリの一部です):
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 ...
}
このファイルを含む小さな単純なプログラムをコンパイルしようとしていますが、リンク時にすべてのラムダへの未定義の参照を取得します。シンプルと言うと、コンパイルはできるがリンクできない単一の CPP があります。ここで最初のエラー:
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&)'
GCC 4.7.2にアップグレードしてから発生しています.GCC 4.6.2(役立つ場合はUbuntuバージョン)で正常に動作していました。問題を解決するための回避策は知っていますが、何が間違っているのか、正しく理解していないのか疑問に思っています。ランバはインライン関数内にあるため、その関数を使用する翻訳単位で定義する必要があります。
- 編集 -
もう 1 つ注目すべき点は、サンプル プログラムではSearch
and関数が使用されていないことです。GetComparer
Search
のメンバー関数で使用されますTable<Description>
(完全なクラスを投稿することはできません):
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);
}
ただし、どちらも sample.cpp ファイルからは呼び出されません。そのファイルは、関連のない他の機能をテストしますTable
。メンバーの呼び出しにコメントを付けると、コードがコンパイルされてリンクされます。(メンバー関数が必要です。これは仮想であり、上記の型消去クラスの一部ですTable
)。