Question

I have some C++ code that includes a method called CreateDirectory(). Previously the code only used STL and Boost, but I recently had to include <windows.h> so I could look-up CSIDL_LOCAL_APPDATA.

Now, this code:

filesystem.CreateDirectory(p->Pathname()); // Actually create it...

No longer compiles:

error C2039: 'CreateDirectoryA' : is not a member of ...

Which corresponds to this macro in winbase.h:

#ifdef UNICODE
#define CreateDirectory  CreateDirectoryW
#else
#define CreateDirectory  CreateDirectoryA
#endif // !UNICODE

The pre-processor is redefining my method call. Is there any possible way to avoid this naming collision? Or do I have to rename my CreateDirectory() method?

Was it helpful?

Solution

You will be better off if you just rename your CreateDirectory method. If you need to use windows APIs, fighting with Windows.h is a losing battle.

Incidently, if you were consistent in including windows.h, this will still be compiling. (although you might have problems in other places).

OTHER TIPS

You could create a module whose sole purpose is to #include <windows.h> and look up CSIDL_LOCAL_APPDATA wrapped in a function.

int get_CSIDL_LOCAL_APPDATA(void)
{
    return CSIDL_LOCAL_APPDATA;
}

btw, Well done for working out what happened!

#undef CreateDirectory

As a developer working on a cross platform codebase, this is a problem. The only way to deal with it is to

  • ensure that windows.h is - on Windows builds at least - universally included. Then the CreateDirectory macro is defined in every one of your compilation units and is universally substituted with CreateDirectoryW. Precompiled headers are ideal for this

OR, if that is an unpleasant proposition, (and it is for me)

  • isolate windows.h usage into windows specific utility files. Create files that export the basic required functionality. The header files must use data types that are compatible with, but do NOT depend on the inclusion of windows.h. The cpp implementation file must (obviously) use windows.h.

If your utlility functions need to include project header files with conflicting symbols then the following pattern is a necessity:

#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...

You will need to then explicitly call the non macro version of any windows api functions you have #undef'd - CreateDirectoryA or W etc.

push macro, undef it and pop the macro again:

#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
 // ...
}
#pragma pop_macro("CreateDirectory")

Note that name conflict usually comes from a certain header file being included. Until then stuff like CreateDirectory and GetMessage isn't pulled into visibility and code compiles without a problem.

You can isolate such an inclusion into a wrapper header file and "#undef whatever" at its end. Then, whatever name collision you have will be gone. Unless, of course, you need to use those macros in your own code (yeah, so very likely...)

You can take a back up of CreateDirectory, then undefine it, and then define it again when you finish your job with you custom one.

#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")

If nothing works, instead of renaming you could use your own namespace for your functions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top