私のコードでは、いくつかのテンプレート パラメーターに依存するラムダ式を含む関数テンプレートを取得しています。最近、おそらく g++ コンパイラの更新が原因で、リンカ エラーが発生しましたが、残念ながら正確にはわかりません。
この問題を示す小さな例を挙げます。これはリンカーの問題であるため、デモ用にいくつかのファイルを作成する必要があります。共通common.hpp
のテンプレート関数を含む 、その関数を利用するa.cpp
/a.hpp
とb.cpp
/の 2 つのモジュール、および関数を含むモジュールがあります。b.hpp
main.cpp
main
// common.hpp
#include <algorithm>
template <class Iterator, typename Iterator::value_type x>
void
my_transform(Iterator begin, Iterator end)
{
std::transform(begin, end, begin,
[] (typename Iterator::value_type y) { return x+y; });
}
ファイルa.cpp
:
// a.cpp
#include "common.hpp"
#include "a.hpp"
void a(std::vector<int>& vec)
{
my_transform<std::vector<int>::iterator, 5>(vec.begin(), vec.end());
}
ファイルa.hpp
#include <vector>
void a(std::vector<int>& vec);
ファイルb.cpp
:
// b.cpp
#include "common.hpp"
#include "b.hpp"
void b(std::vector<int>& vec)
{
my_transform<std::vector<int>::iterator, 5>(vec.begin(), vec.end());
}
ファイルb.hpp
#include <vector>
void b(std::vector<int>& vec);
ファイルmain.cpp
int main() { return 0; }
を使用してコンパイルおよびリンクする場合
g++-4.7 -std=c++11 -c a.cpp
g++-4.7 -std=c++11 -c b.cpp
g++-4.7 -std=c++11 -c main.cpp
g++ a.o b.o main.o
multiple-definition
エラーが発生します:
b.cpp:(.text+0x30): multiple definition of `void my_transform<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, 17>(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >)::{lambda(int)#1}::operator int (*)(int)() const'
a.o:a.cpp:(.text+0x30): first defined here
基本的に、ラムダ式はすでにaで定義されていると言います。わかった。テンプレート パラメータをb
5 から 7 に変更すると、すべてが機能します。
質問:
- これは私が期待すべきことですか、それとも のバグ
g++
ですか? 私はこのコードを以前のバージョンの の debian パッケージでコンパイルしたことを確信していますg++-4.7
。 - ラムダを使用しない以外に回避策はありますか? 結果のシンボルが静的であれば、たとえば問題はないと思います。更新: 回避策: my_transform
static
またはinline
.
この質問はあまり重要ではありません。「ここではラムダを使用しない」というアプローチで問題はありませんが、私は興味があります。:)