From 6010be4144ce126e79a7eee56f5b40eef8085b87 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 06:05:39 +0300 Subject: [PATCH 1/8] Add conversions to std:: counterparts when is available --- include/boost/system/error_code.hpp | 120 +++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 20 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 6ec444f..ed60c52 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -28,6 +28,10 @@ # error BOOST_POSIX_API or BOOST_WINDOWS_API must be defined #endif +#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR +#include +#endif + #include // must be the last #include #ifndef BOOST_SYSTEM_NOEXCEPT @@ -181,10 +185,79 @@ namespace boost // ----------------------------------------------------------------------// + class error_category; + + // predefined error categories -----------------------------------------// + +#ifdef BOOST_ERROR_CODE_HEADER_ONLY + inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; + inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; +#else + BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; + BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; +#endif + // deprecated synonyms --------------------------------------------------// + +#ifndef BOOST_SYSTEM_NO_DEPRECATED + inline const error_category & get_system_category() { return system_category(); } + inline const error_category & get_generic_category() { return generic_category(); } + inline const error_category & get_posix_category() { return generic_category(); } + static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED = generic_category(); + static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED = generic_category(); + static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED = system_category(); +#endif + // class error_category ------------------------------------------------// class error_category : public noncopyable { +#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR + + private: + + class std_category: public std::error_category + { + private: + + boost::system::error_category const * pc_; + + public: + + explicit std_category( boost::system::error_category const * pc ): pc_( pc ) + { + } + + virtual const char * name() const BOOST_NOEXCEPT + { + return pc_->name(); + } + + virtual std::string message( int ev ) const + { + return pc_->message( ev ); + } + + virtual std::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; + }; + + std_category std_cat_; + + public: + + error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} + + operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT + { + if( this == &generic_category() ) + { + return std::generic_category(); + } + + return std_cat_; + } + +#endif + public: virtual ~error_category(){} @@ -204,26 +277,6 @@ namespace boost } }; - // predefined error categories -----------------------------------------// - -# ifdef BOOST_ERROR_CODE_HEADER_ONLY - inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; - inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; -#else - BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; - BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; -#endif - // deprecated synonyms --------------------------------------------------// - -# ifndef BOOST_SYSTEM_NO_DEPRECATED - inline const error_category & get_system_category() { return system_category(); } - inline const error_category & get_generic_category() { return generic_category(); } - inline const error_category & get_posix_category() { return generic_category(); } - static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED = generic_category(); - static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED = generic_category(); - static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED = system_category(); -# endif - // class error_condition -----------------------------------------------// // error_conditions are portable, error_codes are system or library specific @@ -308,12 +361,30 @@ namespace boost || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val); } +#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR + + operator std::error_condition () const BOOST_SYSTEM_NOEXCEPT + { + return std::error_condition( value(), category() ); + } + +#endif + private: int m_val; const error_category * m_cat; }; +#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR + + inline std::error_condition error_category::std_category::default_error_condition( int ev ) const BOOST_NOEXCEPT + { + return pc_->default_error_condition( ev ); + } + +#endif + // class error_code ----------------------------------------------------// // We want error_code to be a value type that can be copied without slicing @@ -402,6 +473,15 @@ namespace boost || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val); } +#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR + + operator std::error_code () const BOOST_SYSTEM_NOEXCEPT + { + return std::error_code( value(), category() ); + } + +#endif + private: int m_val; const error_category * m_cat; From 044c0565b98e0ee7780e9e7588c66e672f6ef8ae Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 14:33:54 +0300 Subject: [PATCH 2/8] Add test for std interop; implement equivalent --- include/boost/system/error_code.hpp | 33 +++-- test/Jamfile.v2 | 6 + test/std_interop_test.cpp | 188 ++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+), 10 deletions(-) create mode 100644 test/std_interop_test.cpp diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index ed60c52..24404ba 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -238,6 +238,7 @@ namespace boost } virtual std::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; + virtual bool equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT; }; std_category std_cat_; @@ -248,7 +249,7 @@ namespace boost operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT { - if( this == &generic_category() ) + if( *this == generic_category() ) { return std::generic_category(); } @@ -376,15 +377,6 @@ namespace boost }; -#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR - - inline std::error_condition error_category::std_category::default_error_condition( int ev ) const BOOST_NOEXCEPT - { - return pc_->default_error_condition( ev ); - } - -#endif - // class error_code ----------------------------------------------------// // We want error_code to be a value type that can be copied without slicing @@ -601,6 +593,27 @@ namespace boost return *this == code.category() && code.value() == condition; } +#ifndef BOOST_NO_CXX11_HDR_SYSTEM_ERROR + + inline std::error_condition error_category::std_category::default_error_condition( int ev ) const BOOST_NOEXCEPT + { + return pc_->default_error_condition( ev ); + } + + inline bool error_category::std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT + { + if( condition.category() == std::generic_category() ) + { + return pc_->equivalent( code, boost::system::error_condition( condition.value(), boost::system::generic_category() ) ); + } + else + { + return default_error_condition( code ) == condition; + } + } + +#endif + } // namespace system } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c6008fc..4195bc8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -55,4 +55,10 @@ project [ run config_test.cpp : : : always_show_run_output ] + [ run std_interop_test.cpp + : : : static + ] + [ run std_interop_test.cpp + : : : shared : std_interop_test_shared + ] ; diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp new file mode 100644 index 0000000..3b7c637 --- /dev/null +++ b/test/std_interop_test.cpp @@ -0,0 +1,188 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/system + +#include + +#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) + +int main() {} + +#else + +#include +#include +#include +#include +#include + +static void test_generic_category() +{ + boost::system::error_category const & bt = boost::system::generic_category(); + std::error_category const & st = bt; + + BOOST_TEST_EQ( &st, &std::generic_category() ); + + BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); + + int ev = ENOENT; + // BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); +} + +static void test_system_category() +{ + boost::system::error_category const & bt = boost::system::system_category(); + std::error_category const & st = bt; + + BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); + + { + int ev = 5; + BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } + + { + int ev = 4; + BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } +} + +class user_category_impl: public boost::system::error_category +{ +public: + + virtual const char * name() const BOOST_NOEXCEPT + { + return "user"; + } + + virtual std::string message( int ev ) const + { + char buffer[ 256 ]; + sprintf( buffer, "user message %d", ev ); + + return buffer; + } + + virtual boost::system::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT + { + if( ev == 4 ) + { + return boost::system::error_condition( EMFILE, boost::system::generic_category() ); + } + else if( ev == 5 ) + { + return boost::system::error_condition( EACCES, boost::system::generic_category() ); + } + else + { + return boost::system::error_condition( ev, *this ); + } + } + + virtual bool equivalent( int code, const boost::system::error_condition & condition ) const BOOST_NOEXCEPT + { + if( code == 4 && condition == make_error_condition( boost::system::errc::too_many_files_open_in_system ) ) + { + return true; + } + + if( code == 4 && condition == make_error_condition( boost::system::errc::too_many_files_open ) ) + { + return true; + } + + return default_error_condition( code ) == condition; + } + + // virtual bool equivalent( const error_code & code, int condition ) const BOOST_NOEXCEPT; +}; + +boost::system::error_category const & user_category() +{ + static user_category_impl cat_; + return cat_; +} + +static void test_user_category() +{ + boost::system::error_category const & bt = user_category(); + std::error_category const & st = bt; + + BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); + + { + int ev = 5; + BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } + + { + int ev = 4; + BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + + { + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } + + { + boost::system::error_condition bn = make_error_condition( boost::system::errc::too_many_files_open_in_system ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } + + { + boost::system::error_condition bn = make_error_condition( boost::system::errc::too_many_files_open ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } + } +} + +int main() +{ + test_generic_category(); + test_system_category(); + test_user_category(); + + return boost::report_errors(); +} + +#endif From 96db439aef03e6db5c49911fe162d38377ea3c35 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 15:07:48 +0300 Subject: [PATCH 3/8] Test exact generic condition values --- test/std_interop_test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp index 3b7c637..961b320 100644 --- a/test/std_interop_test.cpp +++ b/test/std_interop_test.cpp @@ -37,8 +37,14 @@ static void test_generic_category() boost::system::error_condition bn = bt.default_error_condition( ev ); BOOST_TEST( bt.equivalent( ev, bn ) ); + BOOST_TEST_EQ( bn.value(), ev ); + BOOST_TEST_EQ( &bn.category(), &bt ); + std::error_condition sn( bn ); BOOST_TEST( st.equivalent( ev, sn ) ); + + BOOST_TEST_EQ( sn.value(), ev ); + BOOST_TEST_EQ( &sn.category(), &st ); } static void test_system_category() From b722a1ebdab5ccf8ce8d40346991f27060fa43a5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 15:53:02 +0300 Subject: [PATCH 4/8] Add a few more std interop tests --- test/std_interop_test.cpp | 117 +++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp index 961b320..e51b8be 100644 --- a/test/std_interop_test.cpp +++ b/test/std_interop_test.cpp @@ -34,17 +34,40 @@ static void test_generic_category() int ev = ENOENT; // BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); - boost::system::error_condition bn = bt.default_error_condition( ev ); - BOOST_TEST( bt.equivalent( ev, bn ) ); + { + boost::system::error_code bc( ev, bt ); - BOOST_TEST_EQ( bn.value(), ev ); - BOOST_TEST_EQ( &bn.category(), &bt ); + BOOST_TEST_EQ( bc.value(), ev ); + BOOST_TEST_EQ( &bc.category(), &bt ); - std::error_condition sn( bn ); - BOOST_TEST( st.equivalent( ev, sn ) ); + std::error_code sc( bc ); - BOOST_TEST_EQ( sn.value(), ev ); - BOOST_TEST_EQ( &sn.category(), &st ); + BOOST_TEST_EQ( sc.value(), ev ); + BOOST_TEST_EQ( &sc.category(), &st ); + } + + { + boost::system::error_condition bn = bt.default_error_condition( ev ); + + BOOST_TEST_EQ( bn.value(), ev ); + BOOST_TEST_EQ( &bn.category(), &bt ); + + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + + BOOST_TEST_EQ( sn.value(), ev ); + BOOST_TEST_EQ( &sn.category(), &st ); + + BOOST_TEST( st.equivalent( ev, sn ) ); + + std::error_condition sn2 = st.default_error_condition( ev ); + + BOOST_TEST_EQ( sn2.value(), ev ); + BOOST_TEST_EQ( &sn2.category(), &st ); + + BOOST_TEST( st.equivalent( ev, sn2 ) ); + } } static void test_system_category() @@ -58,22 +81,50 @@ static void test_system_category() int ev = 5; BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); - boost::system::error_condition bn = bt.default_error_condition( ev ); - BOOST_TEST( bt.equivalent( ev, bn ) ); + { + boost::system::error_code bc( ev, bt ); - std::error_condition sn( bn ); - BOOST_TEST( st.equivalent( ev, sn ) ); + BOOST_TEST_EQ( bc.value(), ev ); + BOOST_TEST_EQ( &bc.category(), &bt ); + + std::error_code sc( bc ); + + BOOST_TEST_EQ( sc.value(), ev ); + BOOST_TEST_EQ( &sc.category(), &st ); + } + + { + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } } { int ev = 4; BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); - boost::system::error_condition bn = bt.default_error_condition( ev ); - BOOST_TEST( bt.equivalent( ev, bn ) ); + { + boost::system::error_code bc( ev, bt ); - std::error_condition sn( bn ); - BOOST_TEST( st.equivalent( ev, sn ) ); + BOOST_TEST_EQ( bc.value(), ev ); + BOOST_TEST_EQ( &bc.category(), &bt ); + + std::error_code sc( bc ); + + BOOST_TEST_EQ( sc.value(), ev ); + BOOST_TEST_EQ( &sc.category(), &st ); + } + + { + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } } } @@ -145,17 +196,43 @@ static void test_user_category() int ev = 5; BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); - boost::system::error_condition bn = bt.default_error_condition( ev ); - BOOST_TEST( bt.equivalent( ev, bn ) ); + { + boost::system::error_code bc( ev, bt ); - std::error_condition sn( bn ); - BOOST_TEST( st.equivalent( ev, sn ) ); + BOOST_TEST_EQ( bc.value(), ev ); + BOOST_TEST_EQ( &bc.category(), &bt ); + + std::error_code sc( bc ); + + BOOST_TEST_EQ( sc.value(), ev ); + BOOST_TEST_EQ( &sc.category(), &st ); + } + + { + boost::system::error_condition bn = bt.default_error_condition( ev ); + BOOST_TEST( bt.equivalent( ev, bn ) ); + + std::error_condition sn( bn ); + BOOST_TEST( st.equivalent( ev, sn ) ); + } } { int ev = 4; BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + { + boost::system::error_code bc( ev, bt ); + + BOOST_TEST_EQ( bc.value(), ev ); + BOOST_TEST_EQ( &bc.category(), &bt ); + + std::error_code sc( bc ); + + BOOST_TEST_EQ( sc.value(), ev ); + BOOST_TEST_EQ( &sc.category(), &st ); + } + { boost::system::error_condition bn = bt.default_error_condition( ev ); BOOST_TEST( bt.equivalent( ev, bn ) ); From 2d18f6680027a8be1a3ebca12e4dc107c91609af Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 18:43:31 +0300 Subject: [PATCH 5/8] Try to fix g++ 4.x issue with generic_category --- include/boost/system/error_code.hpp | 13 ++++++++++++- test/std_interop_test.cpp | 28 +++++++++++++++++----------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 24404ba..94ef8e2 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -251,7 +251,18 @@ namespace boost { if( *this == generic_category() ) { - return std::generic_category(); + std::error_category const & st = std::generic_category(); + + int ev = ENOENT; + + // if the standard generic category works, use it; else not + if( st.equivalent( ev, st.default_error_condition( ev ) ) ) + { + // g++ 4.x with libstdc++ 5 installed fails, because the two + // generic categories, v1 and v2, get mixed up + + return st; + } } return std_cat_; diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp index e51b8be..4820ee6 100644 --- a/test/std_interop_test.cpp +++ b/test/std_interop_test.cpp @@ -24,15 +24,28 @@ int main() {} static void test_generic_category() { + int ev = ENOENT; + + // check whether the standard generic category works + + std::error_category const & st0 = std::generic_category(); + bool has_roundtrip = st0.equivalent( ev, st0.default_error_condition( ev ) ); + + // + boost::system::error_category const & bt = boost::system::generic_category(); std::error_category const & st = bt; - BOOST_TEST_EQ( &st, &std::generic_category() ); - BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); - int ev = ENOENT; - // BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + if( has_roundtrip ) + { + BOOST_TEST_EQ( &st, &std::generic_category() ); + } + else + { + BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); + } { boost::system::error_code bc( ev, bt ); @@ -60,13 +73,6 @@ static void test_generic_category() BOOST_TEST_EQ( &sn.category(), &st ); BOOST_TEST( st.equivalent( ev, sn ) ); - - std::error_condition sn2 = st.default_error_condition( ev ); - - BOOST_TEST_EQ( sn2.value(), ev ); - BOOST_TEST_EQ( &sn2.category(), &st ); - - BOOST_TEST( st.equivalent( ev, sn2 ) ); } } From c4238c745c215d0f59bd8ae699321ec31cd56ab7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 18:59:15 +0300 Subject: [PATCH 6/8] Add second overload of equivalent, improve first --- include/boost/system/error_code.hpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 94ef8e2..544dcbf 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -239,6 +239,7 @@ namespace boost virtual std::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT; virtual bool equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT; + virtual bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT; }; std_category std_cat_; @@ -613,13 +614,34 @@ namespace boost inline bool error_category::std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT { - if( condition.category() == std::generic_category() ) + if( default_error_condition( code ) == condition ) + { + return true; + } + else if( condition.category() == std::generic_category() ) { return pc_->equivalent( code, boost::system::error_condition( condition.value(), boost::system::generic_category() ) ); } else { - return default_error_condition( code ) == condition; + return false; + } + } + + inline bool error_category::std_category::equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT + { + if( *this == code.category() && code.value() == condition ) + { + return true; + } + else if( *pc_ == boost::system::generic_category() ) + { + std::error_category const & st = std::generic_category(); + return st.equivalent( code, condition ); + } + else + { + return false; } } From bdd1613898d64a3d7a7d3e804253760cb4b13d7f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 20 May 2017 19:33:03 +0300 Subject: [PATCH 7/8] Do not map system::generic to std::generic directly --- include/boost/system/error_code.hpp | 21 ++++----------------- test/std_interop_test.cpp | 20 +++----------------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 544dcbf..81c979b 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -250,22 +250,9 @@ namespace boost operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT { - if( *this == generic_category() ) - { - std::error_category const & st = std::generic_category(); - - int ev = ENOENT; - - // if the standard generic category works, use it; else not - if( st.equivalent( ev, st.default_error_condition( ev ) ) ) - { - // g++ 4.x with libstdc++ 5 installed fails, because the two - // generic categories, v1 and v2, get mixed up - - return st; - } - } - + // do not map generic to std::generic on purpose; occasionally, + // there are two std::generic categories in a program, which leads + // to error codes/conditions mysteriously not being equal to themselves return std_cat_; } @@ -618,7 +605,7 @@ namespace boost { return true; } - else if( condition.category() == std::generic_category() ) + else if( condition.category() == std::generic_category() || condition.category() == boost::system::generic_category() ) { return pc_->equivalent( code, boost::system::error_condition( condition.value(), boost::system::generic_category() ) ); } diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp index 4820ee6..5ee69a8 100644 --- a/test/std_interop_test.cpp +++ b/test/std_interop_test.cpp @@ -24,28 +24,14 @@ int main() {} static void test_generic_category() { - int ev = ENOENT; - - // check whether the standard generic category works - - std::error_category const & st0 = std::generic_category(); - bool has_roundtrip = st0.equivalent( ev, st0.default_error_condition( ev ) ); - - // - boost::system::error_category const & bt = boost::system::generic_category(); std::error_category const & st = bt; BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); - if( has_roundtrip ) - { - BOOST_TEST_EQ( &st, &std::generic_category() ); - } - else - { - BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); - } + int ev = ENOENT; + + BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) ); { boost::system::error_code bc( ev, bt ); From 02262a40484e209801ad5fe4d7f517649d9de690 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 21 May 2017 01:25:09 +0300 Subject: [PATCH 8/8] Test a user-defined error condition category; improve equivalent --- include/boost/system/error_code.hpp | 19 ++++-- test/std_interop_test.cpp | 94 +++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 81c979b..70a41cd 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -607,8 +607,20 @@ namespace boost } else if( condition.category() == std::generic_category() || condition.category() == boost::system::generic_category() ) { - return pc_->equivalent( code, boost::system::error_condition( condition.value(), boost::system::generic_category() ) ); + boost::system::error_code bc( code, *pc_ ); + boost::system::error_condition bn( condition.value(), boost::system::generic_category() ); + + return bc == bn; } +#ifndef BOOST_NO_RTTI + else if( std_category const* pc2 = dynamic_cast< std_category const* >( &condition.category() ) ) + { + boost::system::error_code bc( code, *pc_ ); + boost::system::error_condition bn( condition.value(), *pc2->pc_ ); + + return bc == bn; + } +#endif else { return false; @@ -623,8 +635,7 @@ namespace boost } else if( *pc_ == boost::system::generic_category() ) { - std::error_category const & st = std::generic_category(); - return st.equivalent( code, condition ); + return code == std::error_condition( condition, std::generic_category() ); } else { @@ -644,5 +655,3 @@ namespace boost # endif #endif // BOOST_SYSTEM_ERROR_CODE_HPP - - diff --git a/test/std_interop_test.cpp b/test/std_interop_test.cpp index 5ee69a8..6b9c77d 100644 --- a/test/std_interop_test.cpp +++ b/test/std_interop_test.cpp @@ -120,6 +120,8 @@ static void test_system_category() } } +// test_user_category + class user_category_impl: public boost::system::error_category { public: @@ -251,11 +253,103 @@ static void test_user_category() } } +// test_user2_category + +enum user2_errc +{ + my_enoent = 1, + my_einval, + my_other +}; + +class user2_category_impl: public boost::system::error_category +{ +public: + + virtual const char * name() const BOOST_NOEXCEPT + { + return "user2"; + } + + virtual std::string message( int ev ) const + { + char buffer[ 256 ]; + sprintf( buffer, "user2 message %d", ev ); + + return buffer; + } + + virtual boost::system::error_condition default_error_condition( int ev ) const BOOST_NOEXCEPT + { + return boost::system::error_condition( ev, *this ); + } + + virtual bool equivalent( int code, const boost::system::error_condition & condition ) const BOOST_NOEXCEPT + { + return default_error_condition( code ) == condition; + } + + virtual bool equivalent( const boost::system::error_code & code, int condition ) const BOOST_NOEXCEPT + { + if( code.category() == *this ) + { + return condition == code.value(); + } + else if( condition == my_enoent ) + { + return code == boost::system::errc::no_such_file_or_directory; + } + else if( condition == my_einval ) + { + return code == boost::system::errc::invalid_argument; + } + else + { + return false; + } + } +}; + +boost::system::error_category const & user2_category() +{ + static user2_category_impl cat_; + return cat_; +} + +static void test_user2_category() +{ + boost::system::error_category const & bt = user2_category(); + std::error_category const & st = bt; + + int ev = my_enoent; + + boost::system::error_condition bn( ev, bt ); + + BOOST_TEST_EQ( bn.value(), ev ); + BOOST_TEST_EQ( &bn.category(), &bt ); + + boost::system::error_code bc = make_error_code( boost::system::errc::no_such_file_or_directory ); + + BOOST_TEST( bc == bn ); + + std::error_condition sn( bn ); + + BOOST_TEST_EQ( sn.value(), ev ); + BOOST_TEST_EQ( &sn.category(), &st ); + + std::error_code sc( bc ); + + BOOST_TEST( sc == sn ); +} + +// + int main() { test_generic_category(); test_system_category(); test_user_category(); + test_user2_category(); return boost::report_errors(); }