'make_error_code' 未在此范围内声明,并且在实例化点通过依赖于参数的查找未找到任何声明

'make_error_code' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation

本文关键字:声明 参数 依赖于 任何 查找 code error make 范围内 实例化      更新时间:2023-10-16

我使用boost::system::error_code (boost 1.62.0)在c++中定义自定义错误代码,如下面的示例所示:

#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
namespace mynamespace {
enum class MyErrorCodeEnum : int {
    ERROR1 = 1,
    ERROR2 = 2,
};

class MyErrorCategory: public boost::system::error_category
{
public:
    static const MyErrorCategory& instance() {
        static MyErrorCategory category;
        return category;
    }
    // error_category interface
public:
    virtual const char* name() const noexcept {
        return "MyErrorCategory";
    }
    virtual std::string message(int ev) const {
        return "dummy";
    }
};
}
namespace boost {
namespace system {
inline error_code make_error_code(const mynamespace::MyErrorCodeEnum e) {
    return error_code(static_cast<int>(e), mynamespace::MyErrorCategory::instance());
}
inline error_condition make_error_condition(const mynamespace::MyErrorCodeEnum e) {
    return error_condition(static_cast<int>(e), mynamespace::MyErrorCategory::instance());
}
template<>
struct is_error_code_enum<mynamespace::MyErrorCodeEnum>: public std::true_type {};
}
}

int main(int argc, char *argv[])
{
    throw boost::system::error_code(mynamespace::MyErrorCodeEnum::ERROR1);
}

使用MSVC可以很好地工作。但是,在尝试迁移到mingw 5.3.0时,编译器会报告以下错误:

boost/system/error_code.hpp: In instantiation of 'boost::system::error_code::error_code(ErrorCodeEnum, typename boost::enable_if<boost::system::is_error_code_enum<ErrorCodeEnum> >::type*) [with ErrorCodeEnum = mynamespace::MyErrorCodeEnum; typename boost::enable_if<boost::system::is_error_code_enum<ErrorCodeEnum> >::type = void]':
main.cpp:52:70:   required from here
boost/system/error_code.hpp:329:32: error: 'make_error_code' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
         *this = make_error_code(e);
                                ^
main.cpp:35:19: note: 'boost::system::error_code boost::system::make_error_code(mynamespace::MyErrorCodeEnum)' declared here, later in the translation unit
 inline error_code make_error_code(const mynamespace::MyErrorCodeEnum e) {
                   ^

我可以看到为什么它被报告(make_error_code函数被error_code模板类的构造函数引用后声明),但我该如何解决这个问题?

值得庆幸的是,coliru错误信息更具解释性,以下是一个工作版本:

#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
namespace mynamespace {
enum class MyErrorCodeEnum : int {
    ERROR1 = 1,
    ERROR2 = 2,
};

class MyErrorCategory: public boost::system::error_category
{
public:
    static const MyErrorCategory& instance() {
        static MyErrorCategory category;
        return category;
    }
    // error_category interface
public:
    virtual const char* name() const noexcept {
        return "MyErrorCategory";
    }
    virtual std::string message(int ev) const {
        return "dummy";
    }
};

inline boost::system::error_code make_error_code(const MyErrorCodeEnum e) {
    return boost::system::error_code(static_cast<int>(e), MyErrorCategory::instance());
}
inline boost::system::error_condition make_error_condition(const MyErrorCodeEnum e) {
    return boost::system::error_condition(static_cast<int>(e), MyErrorCategory::instance());
}
}
template<>
struct boost::system::is_error_code_enum<mynamespace::MyErrorCodeEnum>: public std::true_type {};

int main(int argc, char *argv[])
{
    throw boost::system::error_code(mynamespace::MyErrorCodeEnum::ERROR1);
}

clang在coliru上生成的消息:

In file included from main.cpp:1:
/usr/local/include/boost/system/error_code.hpp:329:17: error: call to function 'make_error_code' that is neither visible in the template definition nor found by argument-dependent lookup
        *this = make_error_code(e);
                ^
main.cpp:52:11: note: in instantiation of function template specialization 'boost::system::error_code::error_code<mynamespace::MyErrorCodeEnum>' requested here
    throw boost::system::error_code(mynamespace::MyErrorCodeEnum::ERROR1);
          ^
main.cpp:35:19: note: 'make_error_code' should be declared prior to the call site or in namespace 'mynamespace'
inline error_code make_error_code(const mynamespace::MyErrorCodeEnum e) {
                  ^
1 error generated.

所以,是的,参数依赖查找失败,因为名称空间没有为make_error_code提供实现,所以您必须在模板实例化之前或在相同的名称空间中移动它们。下面是一个类似的问题,答案更详细地解释了这一点。

这也适用于gcc(在is_error_code_enum专门化在boost::system内部的情况下):

#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
namespace mynamespace {
enum class MyErrorCodeEnum : int {
    ERROR1 = 1,
    ERROR2 = 2,
};
}
namespace boost {
namespace system {
template<>
struct is_error_code_enum<mynamespace::MyErrorCodeEnum>: public std::true_type {};
}
}
namespace mynamespace {
class MyErrorCategory: public boost::system::error_category
{
public:
    static const MyErrorCategory& instance() {
        static MyErrorCategory category;
        return category;
    }
    // error_category interface
public:
    virtual const char* name() const noexcept {
        return "MyErrorCategory";
    }
    virtual std::string message(int ev) const {
        return "dummy";
    }
};

inline boost::system::error_code make_error_code(const MyErrorCodeEnum e) {
    return boost::system::error_code(static_cast<int>(e), MyErrorCategory::instance());
}
inline boost::system::error_condition make_error_condition(const MyErrorCodeEnum e) {
    return boost::system::error_condition(static_cast<int>(e), MyErrorCategory::instance());
}
}
int main(int argc, char *argv[])
{
    throw boost::system::error_code(mynamespace::MyErrorCodeEnum::ERROR1);
}