首页 > 解决方案 > 如何使用 std::error_condition?

问题描述

我创建了一个专门的 std::error_category 类。这是我的代码:

#include <system_error>
#include <iostream>
#include <ostream>
#include <string>

//namespace anonymous
 namespace {

// error condition enum
enum class condEnum
{
      ERROR_CODE = 0
    , UNKNOWN_ERROR
};

// error enum
enum class errEnum
{
    ERR_NONE = 0
    ,ERR_A
    ,ERR_B
};

class ErrCategoryClass : public std::error_category
{
    public :

        ErrCategoryClass() noexcept {};
        virtual const char* name() const noexcept override;
        virtual std::string message(int ev) const override;

        std::error_condition default_error_condition(int err_value) const noexcept override;
        bool equivalent(const std::error_code& err_code, int err_value) const noexcept override;
        bool equivalent(int err_value, const std::error_condition& err_cond) const noexcept override;

    private :

        ErrCategoryClass(const ErrCategoryClass&) = delete;
        ErrCategoryClass(ErrCategoryClass&&) = delete;
        ErrCategoryClass& operator=(const ErrCategoryClass&) = delete;
        ErrCategoryClass& operator=(ErrCategoryClass&&) = delete;

}const ErrCategoryClass;

const char* ErrCategoryClass::name() const noexcept
{
    return "Err";
}

std::string ErrCategoryClass::message(int ev) const
{
    std::string aErrStrings[] ={
        "No error"
        ,"Error A"
        ,"Error B"
    };

    std::string libelle = "unknown error";
    if (ev < sizeof(aErrStrings))
        libelle = aErrStrings[ev];
    return libelle;

}

bool ErrCategoryClass::equivalent(const std::error_code& err_code, int err_value) const noexcept
{
    return *this == err_code.category() &&
        static_cast<int>(default_error_condition(err_code.value()).value()) == err_value;
}

bool ErrCategoryClass::equivalent(int err_value, const std::error_condition& err_cond) const noexcept
{
    return default_error_condition(err_value) == err_cond;
}

std::error_condition ErrCategoryClass::default_error_condition(int err_value) const noexcept
{
    condEnum oResult;
    switch (static_cast<errEnum>(err_value))
    {
    case errEnum::ERR_NONE:
    case errEnum::ERR_A:
    case errEnum::ERR_B:
       oResult = condEnum::ERROR_CODE;
    default:
        oResult = condEnum::UNKNOWN_ERROR;

    }
    return std::error_condition(oResult);
}

inline std::error_code make_error_code(errEnum Err)
{
    return std::error_code(static_cast<int>(Err), ErrCategoryClass);
}

inline std::error_condition make_error_condition(condEnum cond) noexcept
{
    return std::error_condition(static_cast<int>(cond), ErrCategoryClass);
}
}

namespace std
{
    template <> struct is_error_condition_enum<condEnum> : public true_type {};
    template <> struct is_error_code_enum<errEnum> : public true_type {};
}

int main()
{
    std::error_code ec = errEnum::ERR_A;

    std::cout << ec.value() << std::endl;
    std::cout << ec.message() << std::endl;

    return EXIT_SUCCESS;
}

我在编译过程中出现以下错误:

错误:没有匹配函数调用 'std::error_condition::error_condition({anonymous}::condEnum&)' return std::error_condition(oResult);

错误:'std::is_error_condition_enum<{anonymous}::condEnum>' 在实例化模板 <> struct is_error_condition_enum 之后的特化:public true_type {}; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

错误:在 test_error.cpp:1 中包含的文件中重新定义 'struct std::is_error_condition_enum<{anonymous}::condEnum>'

我怎样才能解决他的问题?

实施是否正确?

谢谢您的帮助。

标签: c++

解决方案


这是@Igor Tandetnik 建议的更新。这个编译

    #include <system_error>
    #include <iostream>
    #include <ostream>
    #include <string>

    //namespace anonymous
    namespace {

        // error condition enum
        enum class condEnum
        {
            ERROR_CODE = 0
            , UNKNOWN_ERROR
        };

        // error enum
        enum class errEnum
        {
            ERR_NONE = 0
            ,ERR_A
            ,ERR_B
        };

        class ErrCategoryClass : public std::error_category
        {
            public :

                ErrCategoryClass() noexcept {};
                virtual const char* name() const noexcept override;
                virtual std::string message(int ev) const override;

                std::error_condition default_error_condition(int err_value) const noexcept override;
                bool equivalent(const std::error_code& err_code, int err_value) const noexcept override;
                bool equivalent(int err_value, const std::error_condition& err_cond) const noexcept override;

            private :

                ErrCategoryClass(const ErrCategoryClass&) = delete;
                ErrCategoryClass(ErrCategoryClass&&) = delete;
                ErrCategoryClass& operator=(const ErrCategoryClass&) = delete;
                ErrCategoryClass& operator=(ErrCategoryClass&&) = delete;

        }const ErrCategoryClass;

        const char* ErrCategoryClass::name() const noexcept
        {
            return "Err";
        }

        std::string ErrCategoryClass::message(int ev) const
        {
            std::string aErrStrings[] ={
                "No error"
                ,"Error A"
                ,"Error B"
            };

            std::string libelle = "unknown error";
            if (ev < sizeof(aErrStrings))
                libelle = aErrStrings[ev];
            return libelle;

        }

        bool ErrCategoryClass::equivalent(const std::error_code& err_code, int err_value) const noexcept
        {
            return *this == err_code.category() &&
                static_cast<int>(default_error_condition(err_code.value()).value()) == err_value;
        }

        bool ErrCategoryClass::equivalent(int err_value, const std::error_condition& err_cond) const noexcept
        {
            return default_error_condition(err_value) == err_cond;
        }

        std::error_condition ErrCategoryClass::default_error_condition(int err_value) const noexcept
        {
            condEnum oResult;
            switch (static_cast<errEnum>(err_value))
            {
            case errEnum::ERR_NONE:
            case errEnum::ERR_A:
            case errEnum::ERR_B:
            oResult = condEnum::ERROR_CODE;
            default:
                oResult = condEnum::UNKNOWN_ERROR;

            }
            return std::error_condition(oResult);
        }

        inline std::error_code make_error_code(errEnum Err)
        {
            return std::error_code(static_cast<int>(Err), ErrCategoryClass);
        }

        inline std::error_condition make_error_condition(condEnum cond) noexcept
        {
            return std::error_condition(static_cast<int>(cond), ErrCategoryClass);
        }
    }

    namespace std
    {
    template <> struct is_error_condition_enum<condEnum> : public true_type {};
    template <> struct is_error_code_enum<errEnum> : public true_type {};
    }

    int main()
    {
        std::error_code ec = errEnum::ERR_A;

        std::cout << ec.value() << std::endl;
        std::cout << ec.message() << std::endl;

        return EXIT_SUCCESS;
    }

推荐阅读