一部のコードを共有ライブラリに移動しようとしています (スタンドアロンでコンパイルすると正常に動作します) が、クラスのインライン関数で問題が発生します。mingw/gcc v4.7.2。
問題の一部は、クラス宣言の外側でインライン関数を定義することを好むためと思われます (クラス宣言をよりすっきりと読みやすく保ちます)。私はいつもこれが受け入れられ、クラス宣言内で定義することと同等であると考えていました...しかし、常にそうであるとは限りません。問題を示す簡単なサンプルを作成しました。(明らかに、dllexport は通常、インポート/エクスポートを切り替えるマクロ内にあります。)
ヘッダ:
// Uncomment one at a time to see how it compiles with: -O2 -Winline
//#define INLINE_OPTION 1 // implicit - builds without inline warnings
#define INLINE_OPTION 2 // simple external inline - gives inline warnings
//#define INLINE_OPTION 3 // external forced inline - gives inline errors
class __attribute__((dllexport)) Dummy {
public:
Dummy() : m_int{0} {}
~Dummy() {}
#if INLINE_OPTION == 1
int get_int() const { return m_int; }
#else
int get_int() const;
#endif
int do_something();
private:
int m_int;
};
#if INLINE_OPTION == 2
inline int Dummy::get_int() const
{ return m_int; }
#endif
#if INLINE_OPTION == 3
inline __attribute__((always_inline)) int Dummy::get_int() const
{ return m_int; }
#endif
.cpp ファイル:
int Dummy::do_something()
{
int i = get_int();
i *= 2;
return i;
}
上記のように、INLINE_OPTION == 1 (暗黙のクラス内インライン定義) を使用すると、コードは警告なしでコンパイルされます。
INLINE_OPTION == 2 (クラス外のインライン定義) を使用すると、次の警告が表示されます。int Dummy::get_int() const' can never be inlined because it uses attributes conflicting with inlining [-Winline]
INLINE_OPTION == 3 (インラインを強制しようとしている) を使用すると、上記と同じ警告が表示され、さらに次のエラーが表示されます: error: inlining failed in call to always_inline 'int Dummy::get_int() const': function not inlinable
、.cpp ファイルの Dummy::do_something() 内の最初の行から呼び出されていることに関する情報とともに. これは、ライブラリ自体の中で関数をインライン化しようとしていることに注意してください! 単純なアクセサー関数の場合、これは非常に大きなオーバーヘッドになる可能性があります。
私は何か間違ったことをしていますか?クラス外の定義のインライン関数をクラス内の関数定義とは異なる方法で扱うのはgccで正しいですか? (本当にクラス宣言を乱雑にする必要がありますか?)
注: この問題は、インラインで宣言したものだけに影響するわけではありません。また、constexpr として宣言されたものや、継承が関係する場合は "= default" として宣言されたデストラクタにも影響します。
編集:
同じ結果で mingw64 / gcc v4.8.0 を試してみました。これには、オプション 1 が do_something でインライン化されないという事実が含まれていることに注意してください (アセンブラーの出力を確認しました)。そのため、オプション 1 とオプション 2 の唯一の違いは、オプション 2 のみが -Winline 警告を出すことです。