bolero-MURAKAMI / Sprout

C++11/14 constexpr based Containers, Algorithms, Random numbers, Parsing, Ray tracing, Synthesizer, and others.

Home Page:http://bolero-murakami.github.io/Sprout/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Visual Studio2015Update1でリンカーエラー

yumetodo opened this issue · comments

何かしらのヘッダーでsprout/math.hppを読み込みそれを複数のcppでincludeするとLNK2005がでます。
YSRKEN/KanColleSimulator_KAI@3a1191a
で確認しました。
なお、Clang with Microsoft CodeGen (January 2016) では問題は発生しません。

1>------ ビルド開始: プロジェクト:KCS_CUI, 構成:Debug x64 ------
1>  fleet.cpp
1>  コードを生成中...
1>  コンパイル中...
1>  weapon.cpp
1>  simulator.cpp
1>  other.cpp
1>  main.cpp
1>  kammusu.cpp
1>  コードを生成中...
1>kammusu.obj : error LNK2005: "public: static class sprout::array<float,33> const sprout::math::detail::bernoulli_numbers<float>::table" (?table@?$bernoulli_numbers@M@detail@math@sprout@@2V?$array@M$0CB@@4@B) は既に fleet.obj で定義されています。
1>kammusu.obj : error LNK2005: "public: static class sprout::array<double,51> const sprout::math::detail::bernoulli_numbers<double>::table" (?table@?$bernoulli_numbers@N@detail@math@sprout@@2V?$array@N$0DD@@4@B) は既に fleet.obj で定義されています。
1>kammusu.obj : error LNK2005: "public: static class sprout::array<long double,51> const sprout::math::detail::bernoulli_numbers<long double>::table" (?table@?$bernoulli_numbers@O@detail@math@sprout@@2V?$array@O$0DD@@4@B) は既に fleet.obj で定義されています。
1>main.obj : error LNK2005: "public: static class sprout::array<float,33> const sprout::math::detail::bernoulli_numbers<float>::table" (?table@?$bernoulli_numbers@M@detail@math@sprout@@2V?$array@M$0CB@@4@B) は既に fleet.obj で定義されています。
1>main.obj : error LNK2005: "public: static class sprout::array<double,51> const sprout::math::detail::bernoulli_numbers<double>::table" (?table@?$bernoulli_numbers@N@detail@math@sprout@@2V?$array@N$0DD@@4@B) は既に fleet.obj で定義されています。
1>main.obj : error LNK2005: "public: static class sprout::array<long double,51> const sprout::math::detail::bernoulli_numbers<long double>::table" (?table@?$bernoulli_numbers@O@detail@math@sprout@@2V?$array@O$0DD@@4@B) は既に fleet.obj で定義されています。
1>other.obj : error LNK2005: "public: static class sprout::array<float,33> const sprout::math::detail::bernoulli_numbers<float>::table" (?table@?$bernoulli_numbers@M@detail@math@sprout@@2V?$array@M$0CB@@4@B) は既に fleet.obj で定義されています。
1>other.obj : error LNK2005: "public: static class sprout::array<double,51> const sprout::math::detail::bernoulli_numbers<double>::table" (?table@?$bernoulli_numbers@N@detail@math@sprout@@2V?$array@N$0DD@@4@B) は既に fleet.obj で定義されています。
1>other.obj : error LNK2005: "public: static class sprout::array<long double,51> const sprout::math::detail::bernoulli_numbers<long double>::table" (?table@?$bernoulli_numbers@O@detail@math@sprout@@2V?$array@O$0DD@@4@B) は既に fleet.obj で定義されています。
1>simulator.obj : error LNK2005: "public: static class sprout::array<long double,51> const sprout::math::detail::bernoulli_numbers<long double>::table" (?table@?$bernoulli_numbers@O@detail@math@sprout@@2V?$array@O$0DD@@4@B) は既に fleet.obj で定義されています。
1>simulator.obj : error LNK2005: "public: static class sprout::array<float,33> const sprout::math::detail::bernoulli_numbers<float>::table" (?table@?$bernoulli_numbers@M@detail@math@sprout@@2V?$array@M$0CB@@4@B) は既に fleet.obj で定義されています。
1>simulator.obj : error LNK2005: "public: static class sprout::array<double,51> const sprout::math::detail::bernoulli_numbers<double>::table" (?table@?$bernoulli_numbers@N@detail@math@sprout@@2V?$array@N$0DD@@4@B) は既に fleet.obj で定義されています。
1>weapon.obj : error LNK2005: "public: static class sprout::array<float,33> const sprout::math::detail::bernoulli_numbers<float>::table" (?table@?$bernoulli_numbers@M@detail@math@sprout@@2V?$array@M$0CB@@4@B) は既に fleet.obj で定義されています。
1>weapon.obj : error LNK2005: "public: static class sprout::array<double,51> const sprout::math::detail::bernoulli_numbers<double>::table" (?table@?$bernoulli_numbers@N@detail@math@sprout@@2V?$array@N$0DD@@4@B) は既に fleet.obj で定義されています。
1>weapon.obj : error LNK2005: "public: static class sprout::array<long double,51> const sprout::math::detail::bernoulli_numbers<long double>::table" (?table@?$bernoulli_numbers@O@detail@math@sprout@@2V?$array@O$0DD@@4@B) は既に fleet.obj で定義されています。
1>C:\Users\j.pierreno\Documents\git\KanColleSimulator_KAI\KCS_CUI\x64\Debug\KCS_CUI.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

とりあえず応急処置しました。 cb801ff
他の箇所でもリンクエラーが出る可能性が考えられるため、近いうち全体的に処置します。

ちなみにこれ原因はなんですかね?
cb801ff
見てもよくわからない・・・

完全特殊化されたクラステンプレートのstaticメンバ変数の定義が重複していると見做されたようですね。
なので、ワークアラウンドとして、完全特殊化でなく部分特殊化になるようにダミーのテンプレート引数を追加しました。

なるほど・・・。
VSにバグレポ投げるべきなんでしょうか?

8e24d45
同様の問題が出そうな箇所をひととおり修正しました。

修正早い・・・。

規格を参照してみましたが、翻訳単位においてクラステンプレートのstaticデータメンバの定義の重複が許されるのは、非特殊化もしくは部分特殊化の場合であるようです。
なので、これについては VC++ の挙動が規格準拠であると考えられます。

なるほど、勉強になりました。ありがとうございます。

このまま問題ないようでしたら一旦閉じます。

はい