[system] Viral C++11 change would break dependent libraries:-(

Ticket #7278 asks that Boost.System add C++11 noexcept support. A reasonable request, and I implemented it this morning by adding BOOST_NOEXCEPT at the appropriate places specified in the standard. But there is a problem. noexcept is viral, so any classes that inherit from a class that uses noexcept must be changed to also use no except. An example: Boost.Filesystem has this class: class codecvt_error_cat : public boost::system::error_category { public: codecvt_error_cat(){} const char* name() const {return "codecvt";} std::string message(int ev) const; }; Compiling with GCC 4.7 -std=c++0x results in this error: ..\..\../boost/system/error_code.hpp:187:32: error: overriding 'virtual const char* boost::system::error_category::name() const noexcept (true)' To fix it, the filesystem class has to be changed: class codecvt_error_cat : public boost::system::error_category { public: codecvt_error_cat(){} const char* name() const BOOST_NOEXCEPT {return "codecvt";} std::string message(int ev) const; }; I've held off committing the Boost.System changes to trunk until we've had a chance to discuss how to approach this potential break to an unknown number of Boost and user libraries. Ideas? --Beman

On Mon, Aug 27, 2012 at 2:43 PM, Olaf van der Spek <ml@vdspek.org> wrote:
On Mon, Aug 27, 2012 at 7:33 PM, Beman Dawes <bdawes@acm.org> wrote:
Ideas?
Can the derived classes be updated before the superclass is updated? If not, a flag day/release seems necessary which might be problematic for user libs & apps.
That worked OK for Boost.Filesystem's filesystem_error and a UDT that's part of the Boost.System test suite. So that will help with Boost's codebase; we can find and fix the affected code before actually changing Boost.System. But there is still a problem for user code. Also, BOOST_NOEXCEPT is null for C++03 libraries and compilers. But in some cases signature that has to be changed currently has a "throw()" throw-specifier. So I guess we need a BOOST_NOEXCEPT_NOTHROW macro defined as "noexcept" for C++11 and "throw()" for C++03. Otherwise we would be changing the semantics for C++03 compilers. That's similar to what libstdc++ does: // Macro for noexcept, to support in mixed 03/0x mode. #ifndef _GLIBCXX_NOEXCEPT # ifdef __GXX_EXPERIMENTAL_CXX0X__ # define _GLIBCXX_NOEXCEPT noexcept # define _GLIBCXX_USE_NOEXCEPT noexcept # define _GLIBCXX_THROW(_EXC) # else # define _GLIBCXX_NOEXCEPT # define _GLIBCXX_USE_NOEXCEPT throw() # define _GLIBCXX_THROW(_EXC) throw(_EXC) # endif #endif I guess that by defining _GLIBCXX_NOEXCEPT, _GLIBCXX_USE_NOEXCEPT, and _GLIBCXX_THROW(_EXC) yourself, it is possible to build the library from source any way you want. But that runs a serious risk of your library build getting out of sync with your program builds. --Beman

Le 27/08/12 19:33, Beman Dawes a écrit :
Ticket #7278 asks that Boost.System add C++11 noexcept support. A reasonable request, and I implemented it this morning by adding BOOST_NOEXCEPT at the appropriate places specified in the standard.
But there is a problem. noexcept is viral, so any classes that inherit from a class that uses noexcept must be changed to also use no except.
An example: Boost.Filesystem has this class:
class codecvt_error_cat : public boost::system::error_category { public: codecvt_error_cat(){} const char* name() const {return "codecvt";} std::string message(int ev) const; };
Compiling with GCC 4.7 -std=c++0x results in this error:
..\..\../boost/system/error_code.hpp:187:32: error: overriding 'virtual const char* boost::system::error_category::name() const noexcept (true)'
To fix it, the filesystem class has to be changed:
class codecvt_error_cat : public boost::system::error_category { public: codecvt_error_cat(){} const char* name() const BOOST_NOEXCEPT {return "codecvt";} std::string message(int ev) const; };
I've held off committing the Boost.System changes to trunk until we've had a chance to discuss how to approach this potential break to an unknown number of Boost and user libraries.
Ideas?
Hrr, this is really annoying. I have introduced a lot of BOOST_NOEXCEPT in Boost.Chrono and Boost.Thread without thinking that I was changing the interface. Apologies to any one these changes could break their code. One possibility could be to use BOOST_SYSTEM_NOEXCEPT instead. Boost.System could define it depending on the Boost.System version as #if ! defined BOOST_SYSTEM_VERSION #define BOOST_SYSTEM_VERSION 1 #endif #if BOOST_SYSTEM_VERSION < 2 #define BOOST_SYSTEM_NOEXCEPT #else #define BOOST_SYSTEM_NOEXCEPT #endif and let the time to the others libraries to move to the new version. Once all the dependent Boost libraries have made the change, Boost.System could increase the version #if ! defined BOOST_SYSTEM_VERSION #define BOOST_SYSTEM_VERSION 2 #endif The dependent user could always force the Boost.System version. HTH, Vicente

On 27/08/2012 19:33, Beman Dawes wrote:
I've held off committing the Boost.System changes to trunk until we've had a chance to discuss how to approach this potential break to an unknown number of Boost and user libraries.
Just compile all of Boost tests and fix things that break?

2012/8/28 Mathias Gaunard <mathias.gaunard@ens-lyon.org>:
On 27/08/2012 19:33, Beman Dawes wrote:
I've held off committing the Boost.System changes to trunk until we've had a chance to discuss how to approach this potential break to an unknown number of Boost and user libraries.
Just compile all of Boost tests and fix things that break?
Maybe the *AND USER LIBRARIES* should have been better highlighted. cheers, Daniel

On 28/08/2012 17:44, Daniel Pfeifer wrote:
2012/8/28 Mathias Gaunard <mathias.gaunard@ens-lyon.org>:
On 27/08/2012 19:33, Beman Dawes wrote:
I've held off committing the Boost.System changes to trunk until we've had a chance to discuss how to approach this potential break to an unknown number of Boost and user libraries.
Just compile all of Boost tests and fix things that break?
Maybe the *AND USER LIBRARIES* should have been better highlighted.
Simply document it. There should be relatively few users of Boost.System out of Boost itself that extend the provided types and that need to work in C++11. Small problems like these are inherent to upgrading code for C++11 compatibility. Making Boost.System behave more like its counterpart of C++11 is more important (especially since the regression only affects C++11...)

On Mon, Aug 27, 2012 at 1:33 PM, Beman Dawes <bdawes@acm.org> wrote:
Ticket #7278 asks that Boost.System add C++11 noexcept support. A reasonable request, and I implemented it this morning by adding BOOST_NOEXCEPT at the appropriate places specified in the standard.
But there is a problem. noexcept is viral, so any classes that inherit from a class that uses noexcept must be changed to also use no except.
An example: Boost.Filesystem has this class:
class codecvt_error_cat : public boost::system::error_category { public: codecvt_error_cat(){} const char* name() const {return "codecvt";} std::string message(int ev) const; };
Compiling with GCC 4.7 -std=c++0x results in this error:
..\..\../boost/system/error_code.hpp:187:32: error: overriding 'virtual const char* boost::system::error_category::name() const noexcept (true)'
To fix it, the filesystem class has to be changed:
class codecvt_error_cat : public boost::system::error_category { public: codecvt_error_cat(){} const char* name() const BOOST_NOEXCEPT {return "codecvt";} std::string message(int ev) const; };
I've held off committing the Boost.System changes to trunk until we've had a chance to discuss how to approach this potential break to an unknown number of Boost and user libraries.
It looks like the affected Boost libraries are ASIO, Chrono, Filesystem, Thread, and of course System. I'll post a separate message describing a proposed [status] addition to the BOOST_NOEXCEPT* macros. --Beman --Beman
participants (5)
-
Beman Dawes
-
Daniel Pfeifer
-
Mathias Gaunard
-
Olaf van der Spek
-
Vicente J. Botet Escriba