Windowsヘッダーファイルで定義されたマクロとの名前の衝突を避けるにはどうすればよいですか?
質問
呼ばれるメソッドを含むC ++コードがあります CreateDirectory().
以前はコードはSTLとブーストのみを使用していましたが、最近含める必要がありました <windows.h>
だから私は見えることができました CSIDL_LOCAL_APPDATA
.
さて、このコード:
filesystem.CreateDirectory(p->Pathname()); // Actually create it...
コンパイルされなくなりました:
error C2039: 'CreateDirectoryA' : is not a member of ...
これはこのマクロに対応します winbase.h
:
#ifdef UNICODE
#define CreateDirectory CreateDirectoryW
#else
#define CreateDirectory CreateDirectoryA
#endif // !UNICODE
プリプロセッサは私のメソッド呼び出しを再定義しています。この命名の衝突を回避する方法はありますか?または、名前を変更する必要がありますか CreateDirectory()
方法?
解決
createdirectoryメソッドの名前を変更するだけの場合は、より良いでしょう。 Windows APIを使用する必要がある場合、Windows.Hとの戦いは負けた戦いです。
あなたがそうだったら、偶然にも 一貫性のある Windows.hを含めると、これは引き続きコンパイルされます。 (他の場所では問題があるかもしれませんが)。
他のヒント
唯一の目的があるモジュールを作成できます #include <windows.h>
関数に包まれたCSIDL_LOCAL_APPDATAを調べます。
int get_CSIDL_LOCAL_APPDATA(void)
{
return CSIDL_LOCAL_APPDATA;
}
ところで、何が起こったのかを考えてみました!
#undef createdirectory
クロスプラットフォームコードベースに取り組んでいる開発者として、これは問題です。それに対処する唯一の方法はすることです
- Windows.hが - 少なくともWindowsビルドで - 普遍的に含まれていることを確認してください。その後、createdirectoryマクロは、コンピレーションユニットのすべてで定義され、createdirectorywに普遍的に置き換えられます。これに最適です
または、それが不快な提案である場合(そしてそれは私のためです)
- Windows.hの使用をWindows固有のユーティリティファイルに分離します。基本的な必要な機能をエクスポートするファイルを作成します。ヘッダーファイルは、windows.hの包含に依存しないが、互換性のあるデータ型を使用する必要があります。 CPP実装ファイルは、(明らかに)Windows.hを使用する必要があります。
競合するシンボルを持つプロジェクトヘッダーファイルを機能させる必要がある場合、次のパターンが必要です。
#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...
次に、#undef'd -createdirectoryaまたはWなどのWindows API関数の非マクロバージョンを明示的に呼び出す必要があります。
push
大きい、 undef
それと pop
再びマクロ:
#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
// ...
}
#pragma pop_macro("CreateDirectory")
通常、名前の競合は、特定のヘッダーファイルが含まれていることから来ていることに注意してください。それまでは、createdirectoryやgetmessageのようなものは視界に引き込まれておらず、コードコンパイルは問題なくコンパイルされていません。
このような含有をラッパーヘッダーファイルに分離し、最後に「#Undef Whating」に分類できます。その後、あなたが持っている名前の衝突は何でもなくなります。もちろん、あなた自身のコードでそれらのマクロを使用する必要がない限り(ええ、そう とても おそらく...)
バックアップを取ることができます CreateDirectory
, 、それを定義してから、カスタムワンで仕事を終えたら再度定義します。
#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif
// ...
// Define and use your own CreateDirectory() here.
// ...
#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
#pragma push_macro("CreateDirectory")
何も機能しない場合は、名前を変更する代わりに、機能に独自の名前空間を使用できます。