C++ 拉动C++;将类成员枚举到全局命名空间中

C++ 拉动C++;将类成员枚举到全局命名空间中,c++,enums,C++,Enums,是否有using指令将枚举类的成员直接导入编译单元的全局命名空间 我们有: enum Lexeme {....lots of names...}; bool Matches(int lookAhead, Lexeme lxm); 这是有风险的,因为用户经常忘记Matches的第一个参数表示“Matches one”,并写入: if (Matches(ADD,SUB)) ... > C++编译器非常乐意使用添加作为int < /p> 因此,我尝试将Lexeme设置为enum类: enum

是否有
using
指令将
枚举类的成员直接导入编译单元的全局命名空间

我们有:

enum Lexeme {....lots of names...};

bool Matches(int lookAhead, Lexeme lxm);
这是有风险的,因为用户经常忘记
Matches
的第一个参数表示“Matches one”,并写入:

if (Matches(ADD,SUB)) ...
<> > C++编译器非常乐意使用<代码>添加<代码>作为int < /p> 因此,我尝试将
Lexeme
设置为
enum类

enum class Lexeme { ...}
这捕捉到了错误。但现在我的问题是,所有使用
Lexeme
常量的代码都必须写入
enum类
名称:

if (Matches(Lexeme::ADD,Lexeme::SUB)) ...
是否有
使用
指令或其他技巧将所有
词素::*
名称拉入当前范围?注意,大多数令牌都在类中使用(我知道正确地限定常量是
枚举类的安全机制之一)

也许一个更好的计划是将
匹配项
更改为
匹配集
,或者其他什么,以避免出现问题?但我想知道C++和C++的规则,至少.< 我尝试的是:

是相关的,但不处理所需的
enum类
前缀


我还尝试了类似于使用foo::bar::Lexeme的
;但是可惜没有用。

您可以使整型包装器类不能转换为任何其他类型,并从中生成一些常量

struct Lexeme
{
   private: int m_value;

   public: explicit constexpr Lexeme(int value) noexcept
   : m_value{value}
   {}
};

inline constexpr Lexeme const ADD{1};
inline constexpr Lexeme const SUB{2};

为这个类重载一些运算符可能是一个好主意,至少等于和小于。

您可以使整数包装类不可转换为任何其他类,并从中生成一些常量

struct Lexeme
{
   private: int m_value;

   public: explicit constexpr Lexeme(int value) noexcept
   : m_value{value}
   {}
};

inline constexpr Lexeme const ADD{1};
inline constexpr Lexeme const SUB{2};

为此类重载一些运算符可能是一个好主意,至少等于和小于。

另一方面,避免每次编写
词素::
的方法就是创建一个较短的别名:

enum class Lexeme { /* lotsa names */ };
using L = Lexeme;

if (Matches(3, L::SUB)) //...
如果只有一个或两个文件广泛使用了这些值,而其他用途很少,那么这种方法很有效。我刚刚不得不使用一个类似的解决方案,其中我有一个参数类,可以从XML中读取内容。我有一个
enum类ElementType{INTEGER,BOOLEAN,/*etc*/}
和一个解析基础结构。在解析器文件中,我有:

using ET = ElementType;

template<ET et>
struct parser;

// Specializations for each ElementType
template<>
struct parser<ET::INTEGER> {
    using type = int;
    int parseSingle(const string& s) // ...
}
使用ET=ElementType;
模板
结构分析器;
//每个元素类型的专门化
模板
结构分析器{
使用type=int;
int parseSingle(常量字符串&s)/。。。
}

在这个文件之外,我只使用了ElementType::*常量的一些用法,并且使用了enum类的全名。如果这成为一个负担,没有什么可以阻止我将该别名加载到另一个文件。

在另一个注释中,避免每次都写入
词素::
的方法就是创建一个较短的别名:

enum class Lexeme { /* lotsa names */ };
using L = Lexeme;

if (Matches(3, L::SUB)) //...
如果只有一个或两个文件广泛使用了这些值,而其他用途很少,那么这种方法很有效。我刚刚不得不使用一个类似的解决方案,其中我有一个参数类,可以从XML中读取内容。我有一个
enum类ElementType{INTEGER,BOOLEAN,/*etc*/}
和一个解析基础结构。在解析器文件中,我有:

using ET = ElementType;

template<ET et>
struct parser;

// Specializations for each ElementType
template<>
struct parser<ET::INTEGER> {
    using type = int;
    int parseSingle(const string& s) // ...
}
使用ET=ElementType;
模板
结构分析器;
//每个元素类型的专门化
模板
结构分析器{
使用type=int;
int parseSingle(常量字符串&s)/。。。
}

在这个文件之外,我只使用了ElementType::*常量的一些用法,并且使用了enum类的全名。如果这成为一个太大的负担,没有任何东西阻止我将该别名加载到另一个文件。

你在问什么?@DrewDormann我相信OP要求的是一种快捷方式,以避免每次使用枚举时键入
Lexeme::
。你可以使整型包装类不可转换为任何其他类,并从中生成一些常量<代码>类词素{int value;};内联constexpr Lexeme const ADD{1}是。我对其进行了更新,使其更清晰(见顶部的斜体)和更好的标题。@VTT so
const static int
class的成员?,但不会将这些类型作为原始整数,因此无法解决隐式转换问题(将其视为int)?你在问什么?@DrewDormann我相信OP是在问一个快捷方式,以避免每次使用枚举时都键入
Lexeme::
。你可以使整型包装类不能转换为任何其他类,并从中生成一些常量<代码>类词素{int value;};内联constexpr Lexeme const ADD{1}是。我对其进行了更新,以使其更清晰(见顶部的斜体)和更好的标题。@VTT so
const static int
class的成员?,但这些类型不会作为原始整数,因此不会解决隐式转换问题(将其视为int)?这也是一个很好的选择。词法标记通常不会泄漏太多,短前缀几乎和其他前缀一样好。谢谢。这也是一个很好的选择。词法标记通常不会泄漏太多,短前缀几乎和其他前缀一样好。谢谢。如果
Lexeme
enum class
inline constexpr Lexeme ADD{Lexeme::ADD},也可以工作Lexeme
enum class
内联constexpr Lexeme ADD{Lexeme::ADD},则code>也可以工作