2017-07-27 10 views
2

GCC 5.4.0リンカーに非常に奇妙な問題があります。私はこれらのファイルを持っている:ヘッダー専用クラス+関数の未定義参照のみそのクラスのオブジェクトを返す場合

spline.hutils.h/cppmain.cpp

spline.hはスプラインへのフィッティングポイントのヘッダーのみのユーティリティクラスです。

1)私はutils.cppとCMakeのでライブラリを作成します。

add_library(utils_lib utils.cpp) 

utils.hspline.hをINGの#includeです。

2)私はmain.cppから私のバイナリを作成します。私はmain.cpp内でこの機能を使用しようと、そう

tk::spline fitSpline(const std::vector<double>& x, 
        const std::vector<double>& y) 
{ 
    tk::spline output; 
    output.set_points(x,y); 
    return output; 
} 

add_executable(hello_world main.cpp) 
target_link_libraries(hello_world utils_lib) 

3)utils.cppの中では、私はこの機能を持っている

auto my_spline = fitSpline(x,y); 

次に、このリンカーエラーが表示されます。

undefined reference to `fitSpline(std::vector<double, std::allocator<double> > const&, std::vector<double, std::allocator<double> > const&)' 

私は例えばdoublefitSplineの戻り値を変更する場合は:

double fitSpline(const std::vector<double>& x, 
       const std::vector<double>& y) 
{ 
    tk::spline output; 
    output.set_points(x,y); 

    return 0.0; 
} 

それから私はもうリンカエラーを得ることはありません!それはうまくコンパイルされます。私は本当に問題が何か、何かヒントを理解していないのですか?

ありがとうございます!

+0

'utils.h'に' fitSpline'の関数シグネチャはありますか?現時点では私が考えることができるだけです。可能であれば、関連するコードを 'utils。*'と 'main.cpp'に投稿してください。 – hnefatl

+0

@hnefatlはい、署名はそこにあります。私が言ったように、戻り値の型を変更するだけで、すべてうまく動作します。 私は、 'spline.h'は匿名の名前空間にすべてがあることに気付きました。それから、すべてのcppファイルに '#include 'する必要がありますか? – user1011113

+0

本当に[匿名の名前空間](https://stackoverflow.com/questions/154469/unnamed-anonymous-namespaces-vsstatic-functions)にある場合は、ファイルの外部にアクセスできない必要があります。 署名によって、私はあなたが関数の定義と実装を分割しているかどうかを尋ねることができ、そのうちの1つを更新するのを忘れていました。 'main.cpp'に' spline.h'を含めると助けになるかもしれませんが、なぜそれがどうなるかは分かりません。より多くのコードを投稿すると役立ちます。 – hnefatl

答えて

0

2つの翻訳単位があります。 utils_libのTUとmain.cppのTU。

名前のない名前空間の名前は、一意の名前空間にあり、効果的に内部リンケージを持ちます(C++ 11では内部結合を持つように定義されているため)。

したがって、有効な内部リンケージのために、別のTUからtk::splineのようなタイプを参照しようとすると失敗します。

spline.hの複製は、オブジェクトがステートレスで共有されていない場合、通常は問題ありません。しかし、ここであなたはそれをやっていません。 1つのTUにオブジェクトを作成し、別のTUの型を介してオブジェクトを格納しようとすると、それらを代替可能なものとして扱います。名前空間の名前が異なるため、これは失敗します。

ヘッダーのみのライブラリで不要なシンボルをエクスポートしたくない場合は、そのシンボルだけに内部の「詳細」名前空間を使用し、外側の名前空間ではユーザーに知らせる必要があります。

これはどれも、cmakeまたは任意のビルドシステムとは関係ありません。しかし、あなたの質問はcmakeを使用して構造をはっきりさせるので(良い仕事btw)、タグはおそらく上手です。

関連する問題