gpt4 book ai didi

c++ - 是否可以将 boost::system::error_code 转换为 std:error_code?

转载 作者:IT老高 更新时间:2023-10-28 22:13:47 27 4
gpt4 key购买 nike

我想尽可能用标准 C++ 中的等价物替换外部库(如 boost),如果它们存在并且可能的话,以最小化依赖关系,因此我想知道是否存在一种安全的方法来转换 boost::system::error_codestd::error_code。伪代码示例:

void func(const std::error_code & err)
{
if(err) {
//error
} else {
//success
}
}

boost::system::error_code boost_err = foo(); //foo() returns a boost::system::error_code
std::error_code std_err = magic_code_here; //convert boost_err to std::error_code here
func(std_err);

最重要的不是完全相同的错误,只是尽可能接近,最后是否是错误。有什么聪明的解决方案吗?

提前致谢!

最佳答案

我有同样的问题,因为我想使用 std::error_code但也在使用其他使用 boost::system::error_code 的 boost 库(例如 boost ASIO)。接受的答案适用于 std::generic_category() 处理的错误代码,因为它们是 boost 的通用错误代码的简单转换,但它不适用于您想要处理自定义错误类别的一般情况。

所以我创建了以下代码作为通用 boost::system::error_code -to- std::error_code转换器。它通过动态创建 std::error_category 来工作。每个 boost::system::error_category 的垫片,将调用转发到底层 Boost 错误类别。由于错误类别需要是单例(或至少像本例中那样的单例),因此我预计不会有太多的内存爆炸。

我也只是转换 boost::system::generic_category()使用对象std::generic_category()因为它们的行为应该相同。我曾想为 system_category() 做同样的事情,但是在 VC++10 上进行测试时,它打印出了错误的消息(我认为它应该打印出您从 FormatMessage 获得的信息,但它似乎使用了 strerror ,Boost 使用了 FormatMessage 正如预期的那样)。

要使用它,只需调用 BoostToErrorCode() ,定义如下。

只是一个警告,我今天才写这个,所以它只是进行了基本测试。您可以按照自己喜欢的方式使用它,但风险自负。

//==================================================================================================
// These classes implement a shim for converting a boost::system::error_code to a std::error_code.
// Unfortunately this isn't straightforward since it the error_code classes use a number of
// incompatible singletons.
//
// To accomplish this we dynamically create a shim for every boost error category that passes
// the std::error_category calls on to the appropriate boost::system::error_category calls.
//==================================================================================================
#include <boost/system/error_code.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/locks.hpp>

#include <system_error>
namespace
{
// This class passes the std::error_category functions through to the
// boost::system::error_category object.
class BoostErrorCategoryShim : public std::error_category
{
public:
BoostErrorCategoryShim( const boost::system::error_category& in_boostErrorCategory )
:m_boostErrorCategory(in_boostErrorCategory), m_name(std::string("boost.") + in_boostErrorCategory.name()) {}

virtual const char *name() const;
virtual std::string message(value_type in_errorValue) const;
virtual std::error_condition default_error_condition(value_type in_errorValue) const;

private:
// The target boost error category.
const boost::system::error_category& m_boostErrorCategory;

// The modified name of the error category.
const std::string m_name;
};

// A converter class that maintains a mapping between a boost::system::error_category and a
// std::error_category.
class BoostErrorCodeConverter
{
public:
const std::error_category& GetErrorCategory( const boost::system::error_category& in_boostErrorCategory )
{
boost::lock_guard<boost::mutex> lock(m_mutex);

// Check if we already have an entry for this error category, if so we return it directly.
ConversionMapType::iterator stdErrorCategoryIt = m_conversionMap.find(&in_boostErrorCategory);
if( stdErrorCategoryIt != m_conversionMap.end() )
return *stdErrorCategoryIt->second;

// We don't have an entry for this error category, create one and add it to the map.
const std::pair<ConversionMapType::iterator, bool> insertResult = m_conversionMap.insert(
ConversionMapType::value_type(
&in_boostErrorCategory,
std::unique_ptr<const BoostErrorCategoryShim>(new BoostErrorCategoryShim(in_boostErrorCategory))) );

// Return the newly created category.
return *insertResult.first->second;
}

private:
// We keep a mapping of boost::system::error_category to our error category shims. The
// error categories are implemented as singletons so there should be relatively few of
// these.
typedef std::unordered_map<const boost::system::error_category*, std::unique_ptr<const BoostErrorCategoryShim>> ConversionMapType;
ConversionMapType m_conversionMap;

// This is accessed globally so we must manage access.
boost::mutex m_mutex;
};


namespace Private
{
// The init flag.
boost::once_flag g_onceFlag = BOOST_ONCE_INIT;

// The pointer to the converter, set in CreateOnce.
BoostErrorCodeConverter* g_converter = nullptr;

// Create the log target manager.
void CreateBoostErrorCodeConverterOnce()
{
static BoostErrorCodeConverter converter;
g_converter = &converter;
}
}

// Get the log target manager.
BoostErrorCodeConverter& GetBoostErrorCodeConverter()
{
boost::call_once( Private::g_onceFlag, &Private::CreateBoostErrorCodeConverterOnce );

return *Private::g_converter;
}

const std::error_category& GetConvertedErrorCategory( const boost::system::error_category& in_errorCategory )
{
// If we're accessing boost::system::generic_category() or boost::system::system_category()
// then just convert to the std::error_code versions.
if( in_errorCategory == boost::system::generic_category() )
return std::generic_category();

// I thought this should work, but at least in VC++10 std::error_category interprets the
// errors as generic instead of system errors. This means an error returned by
// GetLastError() like 5 (access denied) gets interpreted incorrectly as IO error.
//if( in_errorCategory == boost::system::system_category() )
// return std::system_category();

// The error_category was not one of the standard boost error categories, use a converter.
return GetBoostErrorCodeConverter().GetErrorCategory(in_errorCategory);
}


// BoostErrorCategoryShim implementation.
const char* BoostErrorCategoryShim::name() const
{
return m_name.c_str();
}

std::string BoostErrorCategoryShim::message(value_type in_errorValue) const
{
return m_boostErrorCategory.message(in_errorValue);
}

std::error_condition BoostErrorCategoryShim::default_error_condition(value_type in_errorValue) const
{
const boost::system::error_condition boostErrorCondition = m_boostErrorCategory.default_error_condition(in_errorValue);

// We have to convert the error category here since it may not have the same category as
// in_errorValue.
return std::error_condition( boostErrorCondition.value(), GetConvertedErrorCategory(boostErrorCondition.category()) );
}
}

std::error_code BoostToErrorCode( boost::system::error_code in_errorCode )
{
return std::error_code( in_errorCode.value(), GetConvertedErrorCategory(in_errorCode.category()) );
}

关于c++ - 是否可以将 boost::system::error_code 转换为 std:error_code?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10176471/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com