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