Problem with error_code.hpp dependency on winerror.h

I am wondering why does error_code.hpp include <winerror.h>? All it does is translate the error codes defined in <winerror.h> to a enum values defined in error_code.hpp; however this enum is windows-specific anyway and the user can't use it without <winerror.h>. So, why not leave it up to the user to include <winerror.h> if they care about those values to begin with? My problem is that I get a compile error under Windows, because I (indirectly) include error_code.hpp in my own cpp that is supposed to be platform-independent, and as such it does not see the platform SDK. Emil Dotchevski

Emil Dotchevski wrote:
I am wondering why does error_code.hpp include <winerror.h>?
All it does is translate the error codes defined in <winerror.h> to a enum values defined in error_code.hpp; however this enum is windows-specific anyway and the user can't use it without <winerror.h>. So, why not leave it up to the user to include <winerror.h> if they care about those values to begin with?
Actually, the user *can* use the enum without <winerror.h>.
My problem is that I get a compile error under Windows, because I (indirectly) include error_code.hpp in my own cpp that is supposed to be platform-independent, and as such it does not see the platform SDK.
Hum... Although the library itself needs to see the platform SDK, user code shouldn't be forced to use it. The usual case, however, is that the user does want the platform's enum available. So the Windows default needs to #include <winerror.h>. The question then becomes how to suppress that if not wanted. How about a BOOST_SYSTEM_NO_ENUM macro, which suppresses the system specific enum? --Beman

Actually, the user *can* use the enum without <winerror.h>.
I see this in error_code.hpp: namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = ERROR_INVALID_FUNCTION, file_not_found = ERROR_FILE_NOT_FOUND, path_not_found = ERROR_PATH_NOT_FOUND, .... } } I don't understand how this enum can be compiled without including <winerror.h>.
How about a BOOST_SYSTEM_NO_ENUM macro, which suppresses the system specific enum?
Perhaps the enum should be placed in a platform-specific header, for example "boost/system/windows/error_code.hpp"? Also, how do you feel about replacing the OS-specific enums with plain ints? This way, I can compare error codes directly to the values from <winerror.h> (I understand that enums give us type safety, but unfortunately they can not be incomplete types, which leads to physical coupling and causes the kind of problems I'm hitting with error_code.hpp.) -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
Actually, the user *can* use the enum without <winerror.h>.
I see this in error_code.hpp:
namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = ERROR_INVALID_FUNCTION, file_not_found = ERROR_FILE_NOT_FOUND, path_not_found = ERROR_PATH_NOT_FOUND, .... } }
I don't understand how this enum can be compiled without including <winerror.h>.
The <boost/error_code.hpp> header already includes <winerror.h>, so the user doesn't have to include it.
How about a BOOST_SYSTEM_NO_ENUM macro, which suppresses the system specific enum?
Perhaps the enum should be placed in a platform-specific header, for example "boost/system/windows/error_code.hpp"?
Also, how do you feel about replacing the OS-specific enums with plain ints? This way, I can compare error codes directly to the values from <winerror.h> (I understand that enums give us type safety, but unfortunately they can not be incomplete types, which leads to physical coupling and causes the kind of problems I'm hitting with error_code.hpp.)
The change to enums was made at the request of the C++ committee's library working group, and is reflected in the C++0x standard. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf. I want Boost.System to track the standard as closely as possible. Although the enums take some getting used to, they allow some really useful overloading that cannot be achieved with int's. That overloading (worked out by Chris Kohlhoff) is the key to being able to write both portable and platform-specific code with equal facility. I'll go ahead and put in the BOOST_SYSTEM_NO_ENUM #ifndef. That will at least allow users to avoid the system-specific enums if they wish. But the enums provide a really nice facility for dealing with system-specific errors, so I don't recommend using BOOST_SYSTEM_NO_ENUM except in unusual circumstances. --Beman

On Wed, 31 Oct 2007 19:50:04 -0400, "Beman Dawes" <bdawes@acm.org> said:
Perhaps the enum should be placed in a platform-specific header, for example "boost/system/windows/error_code.hpp"? ... I'll go ahead and put in the BOOST_SYSTEM_NO_ENUM #ifndef. That will at least allow users to avoid the system-specific enums if they wish. But
Emil Dotchevski wrote: the enums provide a really nice facility for dealing with system-specific errors, so I don't recommend using BOOST_SYSTEM_NO_ENUM except in unusual circumstances.
I find the suggestion of separate header files a nice idea. We can restrict system/error_code.hpp to only those interfaces specified for C++0x, and have a header file for each of the OS-specific namespaces (with the same name as the namespace for convenience), i.e. system/windows_error.hpp, system/linux_error.hpp, system/cygwin_error.hpp, and so on. Developers have to use the OS-specific namespace qualification to refer to those error codes anyway, so it doesn't seem like much extra burden to include the additional header file. Cheers, Chris

Christopher Kohlhoff wrote:
On Wed, 31 Oct 2007 19:50:04 -0400, "Beman Dawes" <bdawes@acm.org> said:
Perhaps the enum should be placed in a platform-specific header, for example "boost/system/windows/error_code.hpp"? ... I'll go ahead and put in the BOOST_SYSTEM_NO_ENUM #ifndef. That will at least allow users to avoid the system-specific enums if they wish. But
Emil Dotchevski wrote: the enums provide a really nice facility for dealing with system-specific errors, so I don't recommend using BOOST_SYSTEM_NO_ENUM except in unusual circumstances.
I find the suggestion of separate header files a nice idea. We can restrict system/error_code.hpp to only those interfaces specified for C++0x, and have a header file for each of the OS-specific namespaces (with the same name as the namespace for convenience), i.e. system/windows_error.hpp, system/linux_error.hpp, system/cygwin_error.hpp, and so on. Developers have to use the OS-specific namespace qualification to refer to those error codes anyway, so it doesn't seem like much extra burden to include the additional header file.
OK, I'll do a trial refactoring along those lines. Be a few days, however. --Beman

Actually, the user *can* use the enum without <winerror.h>.
I see this in error_code.hpp:
namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = ERROR_INVALID_FUNCTION, file_not_found = ERROR_FILE_NOT_FOUND, path_not_found = ERROR_PATH_NOT_FOUND, .... } }
I don't understand how this enum can be compiled without including <winerror.h>.
The <boost/error_code.hpp> header already includes <winerror.h>, so the user doesn't have to include it.
Seems like there is some kind of misunderstanding. :) My original problem was triggered by the fact that "boost/error_code.hpp" *attempts* to include <winerror.h>, and on my Windows system <winerror.h> is not accessible "just like that" (I am including "boost/error_code.hpp" in a CPP file which, although being built using MSVC on Windows, does not see the platform SDK because it's platform independent.)
I'll go ahead and put in the BOOST_SYSTEM_NO_ENUM #ifndef. That will at least allow users to avoid the system-specific enums if they wish. But the enums provide a really nice facility for dealing with system-specific errors, so I don't recommend using BOOST_SYSTEM_NO_ENUM except in unusual circumstances.
I wouldn't call compiling platform-independent cpp files on Windows "unusual circumstance". -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
Actually, the user *can* use the enum without <winerror.h>. I see this in error_code.hpp:
namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = ERROR_INVALID_FUNCTION, file_not_found = ERROR_FILE_NOT_FOUND, path_not_found = ERROR_PATH_NOT_FOUND, .... } }
I don't understand how this enum can be compiled without including <winerror.h>. The <boost/error_code.hpp> header already includes <winerror.h>, so the user doesn't have to include it.
Seems like there is some kind of misunderstanding. :)
My original problem was triggered by the fact that "boost/error_code.hpp" *attempts* to include <winerror.h>, and on my Windows system <winerror.h> is not accessible "just like that" (I am including "boost/error_code.hpp" in a CPP file which, although being built using MSVC on Windows, does not see the platform SDK because it's platform independent.)
Most (all?) msdn documentation pages say to include <windows.h> to access a part of the win32 api even if it is declared in a different header. I know that when targeting Windows Mobile 5 with VS2005 you get a horde of error messages if you try to include headers like <winuser.h> directly. Couldn't the definitions be changed to something like namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = 1, //ERROR_INVALID_FUNCTION ... } } A bit more fragile but removes the dependency on winerror.h Or is this too evil? Thanks, Michael Marcin

Most (all?) msdn documentation pages say to include <windows.h> to access a part of the win32 api even if it is declared in a different header. I know that when targeting Windows Mobile 5 with VS2005 you get a horde of error messages if you try to include headers like <winuser.h> directly.
Couldn't the definitions be changed to something like
namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = 1, //ERROR_INVALID_FUNCTION ... } }
A bit more fragile but removes the dependency on winerror.h
Or is this too evil?
Whether or not it's evil depends on how likely it is for these values to change across the Windows family of OSes; I can speculate that they do no vary. But I think that a separate header solution is preferable, because the windows_error_code enum is windows-specific anway. -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
Actually, the user *can* use the enum without <winerror.h>.
I see this in error_code.hpp:
namespace windows_error { enum windows_error_code { success = 0, // These names and values are based on Windows winerror.h invalid_function = ERROR_INVALID_FUNCTION, file_not_found = ERROR_FILE_NOT_FOUND, path_not_found = ERROR_PATH_NOT_FOUND, .... } }
I don't understand how this enum can be compiled without including <winerror.h>.
How about a BOOST_SYSTEM_NO_ENUM macro, which suppresses the system specific enum?
Perhaps the enum should be placed in a platform-specific header, for example "boost/system/windows/error_code.hpp"?
Also, how do you feel about replacing the OS-specific enums with plain ints? This way, I can compare error codes directly to the values from <winerror.h> (I understand that enums give us type safety, but unfortunately they can not be incomplete types, which leads to physical coupling and causes the kind of problems I'm hitting with error_code.hpp.)
This reminds me of http://www.ddj.com/cpp/184403894
participants (4)
-
Beman Dawes
-
Christopher Kohlhoff
-
Emil Dotchevski
-
Michael Marcin