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