UE4/C++ FORCEINLINE にしたいけど Debug ビルドの時は inline 最適化されたくない関数を定義する方法
#ifndef UE_BUILD_DEBUG
FORCEINLINE
#endif
void hogehoge()
{ /* fugafuga */ }
と、いうわけで #ifdef でOK。 Debug ビルドで定義される UE_BUILD_DEBUG の他に Development ビルドで定義される UE_BUILD_DEVELOPMENT もあるので用途に応じて使う。
あるいは UE_BUILD_xxxx シリーズのマクロについて
これらのマクロのシリーズは公式ドキュメント的にはたぶんアンドキュメント。ソースを見るとこのプリフィックスのシリーズは
Engine/Source/Runtime/Core/Public/Misc/Build.h に、
UE_BUILD_DEBUGUE_BUILD_DEVELOPMENTUE_BUILD_TESTUE_BUILD_SHIPPINGUE_BUILD_SHIPPIING_WITH_EDITORUE_BUILD_DOCSUE_BUILD_FINAL_RELEASEUE_BUILD_MINIMAL
の存在を UE-4.16 現在、確認できる。
追記: FORCEINLINE_DEBUGGABLE について
↑までの内容でブログを書いた後もしばらくソースを眺めていると、 FORCEINLINE_DEBUGGABLE マクロの定義もあることに気付いた。これを使うと、
FORCEINLINE_DEBUGGABLE void hogehoge()
{ /* fugafuga */ }
こんな具合で簡単化できて嬉しいのかなー・・・と思ったものの、ちょっと違った。冒頭で紹介した #ifdef の代わりに使ってしまうと FORCEINLINE ほどではないもののデバッグ実行は実際問題としては難しくなってしまう。
UE_BUILD_xxxx シリーズや FORCEINLINE_DEBUGGABLE は Engine/Source/Runtime/Core/Public/Misc/Build.h で定義されていて、 FORCEINLINE_DEBUGGABLE は FORCEINLINE_DEBUGGABLE_ACTUAL へ置換される。それから
Engine/Source/Runtime/Core/Public/HAL/Platform.h で FORCEINLINE_DEBUGGABLE_ACTUAL が"未定義"の場合には FORCEINLINE_DEBUGGABLE_ACTUAL は inline と定義される。
つまり、そんなこんなで少し入り組んでいるものの、ともかく FORCEINLINE_DEBUGGABLE を使うと C++ キーワードの inline と同様の挙動で inline 最適化が指示された関数を定義した事になる。
ちなみに、 FORCEINLINE は C++ キーワードの inline ではなくて、コンパイラーの独自拡張によるより強制力の高い inline 関数を指示するキーワードへ置換される UE4 定義のマクロで、例えば cl.exe(MSVC++) なら __forceinline に置換されたりする。UE4 が対応する FORCEINLINE のプラットフォームごとの対応は Engine/Source/Runtime/Core/Public/<PLATFORM>/<PLATFORM>Platform.h でそれぞれに定義されていて、
| 置換先 | |
|---|---|
| Android | __attribute__ ((always_inline)) |
| iOS | __attribute__ ((always_inline)) |
| Linux | __attribute__ ((always_inline)) |
| Mac | __attribute__ ((always_inline)) |
| Windows | __forceinline |
こんな感じに定義されている。
参考
- https://github.com/EpicGames/UnrealEngine/blob/4.16/Engine/Source/Runtime/Core/Public/Misc/Build.h
- How can I differentiate between Macros for DebugGame Editor vs Development Editor? - UE4 AnswerHub