реализация std :: error_category, проблема разрешения имен при использовании с пользовательскими пространствами имен - PullRequest
0 голосов
/ 12 июня 2019

Короче говоря , проблема заключается в разрешении имени.

Объяснение: Я перечисляю коды ошибок и использую их для получения / реализации класса std::error_condition, однакоСуществует проблема при переносе реализации в 2 отдельных пространства имен, одно для перечислений и другое для реализации кода.

Это нелегко объяснить, поэтому я создал минимально компилируемый код, который вы можете просто скопировать / вставить в редактор и попробоватьдля компиляции.

Я поместил (NOTE :) комментарий поверх кода, что я и делаю для компиляции кода, но мне нужны отдельные пространства имен, как показано в коде ниже, но разрешение имен нене работает, и я не знаю, как это исправить.

#include <string>
#include <system_error>


// *NOTE*: if we rename this from 'enums' to 'app' (comment below) and do
// the needed name change changes in the code it will compile just fine
//namespace app
namespace enums
{
    // error type enum
    enum class Error
    {
        SignalFail,         // failed to set up or execute signal
        BadArgument,        // bad argument passed to function
        InvalidPointer,     // Pointer is invalid
        NoImplementation,   // No implementation
        OutOfRange,         // Out of range
        AlocationFailed,    // Failed to alocate memory
        MemoryReadFailed,   // Failed to read memory
        Unexpected          // Unexpected execution flow
    };

    // error condition enum
    enum class Condition
    {
        code_error,
        unknown_error
    };
}

// Register Error and Condition as error enum and condition enum
namespace std
{
    template<>
    struct is_error_code_enum<enums::Error> :
        public true_type {};

    template<>
    struct is_error_condition_enum<enums::Condition> :
        public true_type {};
}

namespace app
{
    // Category types are used to identify the source of an error.
    // They also define the relation between error_code and error_condition objects of its category,
    // as well as the message set for error_code objects.
    class error_category_t :
        public std::error_category
    {
    public:
        error_category_t() noexcept {};
        inline const char* name() const noexcept override;
        std::error_condition default_error_condition(int err_value) const noexcept override;
        inline bool equivalent(const std::error_code& err_code, int err_value) const noexcept override;
        inline bool equivalent(int err_value, const std::error_condition& err_cond) const noexcept override;
        std::string message(int ev) const override;
    private:
        error_category_t(const error_category_t&) = delete;
        error_category_t(error_category_t&&) = delete;
        error_category_t& operator=(const error_category_t&) = delete;
        error_category_t& operator=(error_category_t&&) = delete;
    } const error_category;

    const char* error_category_t::name() const noexcept
    {
        return "app category";
    }

    bool error_category_t::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 error_category_t::equivalent(int err_value, const std::error_condition& err_cond) const noexcept
    {
        return default_error_condition(err_value) == err_cond;
    }

    //
    // make_error_condition overload to generate custom conditions:
    // This function is called by error_condition's constructor for error condition enum types,
    // and should be overloaded for all custom error condition enum types in order to
    // provide a mechanism to generate the appropriate error_condition objects from them.
    //
    inline std::error_condition make_error_condition(enums::Condition ec) noexcept
    {
        return std::error_condition(static_cast<int>(ec), error_category);
    }

    //
    // This function is called by error_code's constructor for error code enum types
    //
    inline std::error_code make_error_code(enums::Error code) noexcept
    {
        return std::error_code(static_cast<int>(code), error_category);
    }
}

namespace app
{
    std::error_condition error_category_t::default_error_condition(int err_value) const noexcept
    {
        switch (static_cast<enums::Error>(err_value))
        {
        case enums::Error::SignalFail:
        case enums::Error::BadArgument:
        case enums::Error::InvalidPointer:
        case enums::Error::NoImplementation:
        case enums::Error::OutOfRange:
        case enums::Error::AlocationFailed:
        case enums::Error::MemoryReadFailed:
        case enums::Error::Unexpected:
            return std::error_condition(enums::Condition::code_error);
        default:
            return std::error_condition(enums::Condition::unknown_error);
        }
    }

    std::string error_category_t::message(int err_value) const
    {
        switch (static_cast<enums::Error>(err_value))
        {
        case enums::Error::SignalFail:
            return "Signaling failed";
        case enums::Error::BadArgument:
            return "Bad Argument";
        case enums::Error::InvalidPointer:
            return "Invalid pointer";
        case enums::Error::NoImplementation:
            return "No implementation";
        case enums::Error::OutOfRange:
            return "Out of range";
        case enums::Error::AlocationFailed:
            return "Memory allocation failed";
        case enums::Error::MemoryReadFailed:
            return "Memory read failed";
        case enums::Error::Unexpected:
            return "Unexpected execution flow";
        default:
            return "Unknown error";
        }
    }
}

1 Ответ

0 голосов
/ 12 июня 2019

Хотя я лично рекомендую помещать перечисления в то же пространство имен, что и категория, ключевая проблема заключается в том, что функции make_error_condition и make_error_code должны находиться в том же пространстве имен, что и перечисления.Оба конструктора std::error_code и std::error_condition выполняют поиск ADL этих двух функций.

inline std::error_condition make_error_condition(enums::Condition ec) noexcept
inline std::error_code make_error_code(enums::Error code) noexcept
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...