gpt4 book ai didi

c++ - is_error_code_enum<> 枚举必须仅在全局命名空间中定义?

转载 作者:太空狗 更新时间:2023-10-29 21:19:17 24 4
gpt4 key购买 nike

我正在尝试创建我自己的基于枚举的错误类别,并希望我的带有错误代码的枚举在某个命名空间内定义。令我惊讶的是,这阻止了我的枚举值自动转换为 std::error_code (如果枚举是在全局命名空间中定义的,则这种转换有效)。

#include <system_error>

namespace NS { enum class X {a,b,c}; }
using NS::X;

class X_category : public std::error_category
{
public:
virtual const char *name() const noexcept override { return "X"; }
virtual std::string message(int ev) const override { return ""; }
};

inline const std::error_category& X_category()
{
static class X_category c; return c;
}

template<> struct std::is_error_code_enum<X> : public std::true_type{};

inline std::error_code make_error_code(X result)
{
return std::error_code(static_cast<int>(result), X_category());
}

int main()
{
std::error_code e = X::a; // does not work !!
}

我是否在上面的代码中遗漏了一些东西(可能与重载解析规则有关)以使其工作?或者为 std::is_error_code_enum<> 做枚举只能在全局命名空间内定义??

编辑。我的编译器(MSVC2013)没有提示它,但似乎 std::is_error_code_enum<> 的特化必须在 std 命名空间内完成。此外,我在 name() 方法上添加了 noexcept 关键字,使代码更加符合 C++11(MSVC2013 不理解 noexcept,但 MSVC2015 会)。

编辑2。根据 C++11 14.7.3.2 [temp.expl.spec]:

An explicit specialization shall be declared in a namespace enclosing the specialized template.

因此没有必要将 std::is_error_code_enum<> 的特化放在 std 命名空间中。 MSVC 正确编译它,但 GCC 提示这实际上是 GCC 中的一个错误,因为 GCC 遵循更严格的旧 C++03 规则。

最佳答案

来自 error_code 的构造函数模板确实在重载决策中被考虑 - 您正确地特化了 is_error_code。问题是 error_code 构造函数模板定义中这一行的 ADL:

*this = make_error_code(__e);

ADL 不考虑全局命名空间,因为X 只在NS 中定义,而不是全局命名空间。 [basic.lookup.argdep]/(2.3):

If T is an enumeration type, its associated namespace is the innermost enclosing namespace of its declaration. [..]

using 声明不会改变这一点。 [basic.lookup.argdep]/2:

The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set.

要解决此问题,请将您的 make_error_code 添加到 NS:

namespace NS {
inline std::error_code make_error_code(X result)
{
return std::error_code(static_cast<int>(result), X_category());
}
}

Demo .

关于c++ - is_error_code_enum<> 枚举必须仅在全局命名空间中定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27764647/

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