インライン非メンバー関数内のローカル クラスは MSVC2005 で LNK2005 を生成します
-
21-09-2019 - |
質問
どうやら、MSVC2005 はローカル クラスのメンバー関数のインライン化に失敗し、LNK2005 が発生するようです。
次のものをコンパイルすると、この LNK2005 エラーが発生します。
common.h
コンテンツ:
inline void wait_what()
{
struct wtf
{
void ffffuuu() {}
} local;
}
foo.cpp
コンテンツ:
#include "common.h"
void foo()
{
wait_what();
}
bar.cpp
コンテンツ:
#include "common.h"
void bar()
{
wait_what();
}
LNK2005.cpp の内容:
// forward declarations
void foo();
void bar();
int main()
{
foo();
bar();
return 0;
}
エラーメッセージは次のとおりです。
error LNK2005: "public void __thiscall `void__cdecl wait_what(void)'::`2'::wtf::ffffuuu(void)" (?ffffuuu@wtf?1??wait_what@@YAXXZ@QAEXXZ) already defined in bar.obj
ローカル クラスについて、ISO IEC 14882-2003 には次のように記載されています。
9.8 ローカルクラス宣言
クラスは関数定義内で定義できます。そのようなクラスは と呼ばれます 地元 クラス。ローカル クラスの名前は、それを囲むスコープに対してローカルです。ローカル クラスは、外側のスコープのスコープ内にあり、外側の関数と同じように関数の外部の名前にアクセスできます。ローカル クラスの宣言では、型名、静的変数、外部変数と関数、および外側のスコープの列挙子のみを使用できます。
囲んでいる関数には、ローカル クラスのメンバーに対する特別なアクセス権はありません。通常のアクセス規則 (第 11 条) に従います。ローカル クラスのメンバー関数は、定義されている場合には、そのクラス定義内で定義されます。
私は何か見落としてますか?
私には、それはコンパイラのバグのように思えます。GCC と MSVC2008 は問題なくコンパイルします。ただし、本当に呼び出しをインライン化するのか、それともリンク フェーズ中に 2 つのシンボルのうち 1 つを破棄するだけなのかは疑問です。興味深いことに、このローカル クラス メンバー関数への呼び出しさえないことに気づくことができます。
MSVC2005の回避策はあるのでしょうか。この典型的な問題について MSDN を検索しようとしましたが、あまり成功しませんでした。コンパイラの既知のバグのリストを見つけることさえできませんでした。
添付ファイル: LNK2005.zip
解決
これは、Visual Studio 2005のバグだった、それはVS 2008で修正されました。
他のヒント
これは、私にはバグのように見えます。それはVS2008で動作する理由多分それです。 (ちなみに、Microsoftは、これは、Visual StudioのIDE /コンパイラの依存関係を壊すための十分な理由です。)
この問題を回避するためとして、inline
を追加、またはwait_what
をインライン化しませ明示的にしてみてください。