c++ typedef 另一个类的枚举?

发布于 2024-07-20 09:23:16 字数 372 浏览 8 评论 0原文

所以这是我的问题:

struct A
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };
};

struct B
{
    typedef A::A_enum B_enum;
    bool test(B_enum val)
    {
        return (val == E1); // error: "E1" undeclared identifier
    }
};

我特别不想说 A::E1。 如果我尝试 B_enum::E1 我会收到一条警告,指出它是非标准的。 有没有好的方法来做这样的事情?

So here's my problem:

struct A
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };
};

struct B
{
    typedef A::A_enum B_enum;
    bool test(B_enum val)
    {
        return (val == E1); // error: "E1" undeclared identifier
    }
};

I specifically do not want to say A::E1. If I try B_enum::E1 I receive a warning that it is nonstandard. Is there a good way to do something like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

回忆追雨的时光 2024-07-27 09:23:16

我认为 A 应该是一个命名空间而不是一个结构体。

I reckon that A should be a namespace instead of a struct.

陌生 2024-07-27 09:23:16

将枚举放在全局范围内太过暴露,将它们放在类中可能会引入不需要的依赖关系。 对于与类没有紧密链接的枚举,这就是我使用的:

#define CLEANENUMS_BEGIN(name) namespace name { typedef enum {
#define CLEANENUMS_END(name) } internal_ ## name ## _e;} typedef name::internal_ ## name ## _e name ## _e;

然后您可以在全局范围内使用:

CLEANENUMS_BEGIN(myEnum)
    horizontal,
    vertical,
CLEANENUMS_END(myEnum)

这或多或少模拟了处理枚举范围的 C# 方式。 预处理器将生成以下代码:

namespace myEnum
{
    enum internal_myEnum_e
    {
        horizontal,
        vertical,
    }
}
typedef internal_myEnum_e myEnum_e;

然后将给定的枚举引用为

myEnum_e val = myEnum::horizontal;

希望有更好的方法来执行此操作,但到目前为止,这是我找到的唯一解决方案。

Putting enum in global scope is too exposed, putting them in a class can introduced undesired dependency. For enum not tightly link to a class, this is what I use:

#define CLEANENUMS_BEGIN(name) namespace name { typedef enum {
#define CLEANENUMS_END(name) } internal_ ## name ## _e;} typedef name::internal_ ## name ## _e name ## _e;

Then you can use, at global scope:

CLEANENUMS_BEGIN(myEnum)
    horizontal,
    vertical,
CLEANENUMS_END(myEnum)

That is more or less emulating C# way of handling enums scope. The preprocessor will produce this code:

namespace myEnum
{
    enum internal_myEnum_e
    {
        horizontal,
        vertical,
    }
}
typedef internal_myEnum_e myEnum_e;

Then a given enum is referenced as

myEnum_e val = myEnum::horizontal;

Hopefully there's a better way of doing this but so far, that's the only solution I found.

万劫不复 2024-07-27 09:23:16

我过去也遇到过同样的问题,这就是我解决它的方法。
我希望能够在编译时切换库的实现。
其中一个库使用了如下代码:

namespace Lib1 
{
  enum LibEnum { One, Two, Three };
  [...]
  void someFunc(LibEnum val);
}

在我的代码中,我想从用户体验中隐藏库实现(因此我的代码的用户永远不应该看到我在内部使用的库):

解决方案 1:

namespace MyCode 
{
  // Example to avoid copying a function from Lib1 here
  typedef Lib1::someFunc aFunctionImUsing;

  // This doesn't work
  // typedef LibEnum MyEnum; 
  // As such code doesn't compile:
  // aFunctionImUsing(One); // Error unknown identifier One
  // But this did:
  struct Type
  {
     enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
  }
  static inline Lib1::LibEnum as(Type::MyType t) { return (Lib1::LibEnum)t; }

  // Now code like this compiles:
  aFunctionImUsing(as(Type::One));
  // This one doesn't:
  // aFunctionImUsing(Type::One); // Can't convert from Type::MyType to Lib1::LibEnum

  [...]
}

解决方案 2:

namespace MyCode 
{
  struct Type
  {
     enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
  }

  // If you don't care about polluting your namespace with numerous wrapper 
  // you can write this instead of typedef someFunc:
  static inline void myFunc(Type::MyType t) { return Lib1::someFunc((Lib1::LibEnum)t); }

  // This one does:
  myFunc(Type::One); 
  [...]
}

它们是上面代码片段的两个问题。 第一个问题是你必须复制并复制它。 将枚举粘贴到您的命名空间中(但在查找和替换中使用简单的正则表达式,就完成了)。
第二个问题是您的用户必须使用“as”方法,这意味着它并不简单,或者您必须使用第二个解决方案包装方法/函数。

不管怎样,由于不可能跨命名空间注入枚举,所以这个解决方案是你能做的最好的解决方案。 请注意,您的代码用户甚至不知道您在示例代码中使用 Lib1 库。

I've had the same issue in the past, and this is how I've fixed it.
I wanted to be able to switch the implementation of a library at compile time.
One of the lib was using code like this:

namespace Lib1 
{
  enum LibEnum { One, Two, Three };
  [...]
  void someFunc(LibEnum val);
}

In my code, I wanted to hide the library implementation from the user experience (so a user of my code should never see what lib I'm using internally):

Solution 1:

namespace MyCode 
{
  // Example to avoid copying a function from Lib1 here
  typedef Lib1::someFunc aFunctionImUsing;

  // This doesn't work
  // typedef LibEnum MyEnum; 
  // As such code doesn't compile:
  // aFunctionImUsing(One); // Error unknown identifier One
  // But this did:
  struct Type
  {
     enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
  }
  static inline Lib1::LibEnum as(Type::MyType t) { return (Lib1::LibEnum)t; }

  // Now code like this compiles:
  aFunctionImUsing(as(Type::One));
  // This one doesn't:
  // aFunctionImUsing(Type::One); // Can't convert from Type::MyType to Lib1::LibEnum

  [...]
}

Solution 2:

namespace MyCode 
{
  struct Type
  {
     enum MyType { One = Lib1::One, Two = Lib1::Two, Three = Lib1::Three };
  }

  // If you don't care about polluting your namespace with numerous wrapper 
  // you can write this instead of typedef someFunc:
  static inline void myFunc(Type::MyType t) { return Lib1::someFunc((Lib1::LibEnum)t); }

  // This one does:
  myFunc(Type::One); 
  [...]
}

They are 2 issues with the code fragment above. The first issue is that you must copy & paste the enum inside your namespace, (but with a simple regular expression in find&replace, you're done).
The second issue is that your user will have to use the "as" method, which means that it's not straightforward, or you have to wrap the method/function using the second solution.

Anyway, as it's not possible to inject an enum across namespace, this solution is the best you can do. Notice that your code user don't even know you're using the Lib1 library in the example code.

菩提树下叶撕阳。 2024-07-27 09:23:16

我遇到了同样的问题,我使用了这个解决方案,而不是使用多余的命名空间。 它将枚举安全地隐藏在类及其显式用户中。

class TreeWindow abstract {
public:
  enum CheckState { On, Off, Partial }
};

class TreeControl abstract {
public:
  class ItemChecked abstract: public TreeWindow { // this is the hack needed
  public:
    using TreeWindow::CheckState;
  };

  void func(ItemChecked::CheckState);
};

TreeControl& tree = ...
tree.func(TreeControl::ItemChecked::Partial);

I had the same problem, and I used this solution instead of screwing around with superfluous namespaces. It keeps the enum safely hidden inside the class and its explicit users.

class TreeWindow abstract {
public:
  enum CheckState { On, Off, Partial }
};

class TreeControl abstract {
public:
  class ItemChecked abstract: public TreeWindow { // this is the hack needed
  public:
    using TreeWindow::CheckState;
  };

  void func(ItemChecked::CheckState);
};

TreeControl& tree = ...
tree.func(TreeControl::ItemChecked::Partial);
倾`听者〃 2024-07-27 09:23:16

看来没有一个简单的解决方案。 也困扰我。
如果您被允许更改 A,并且不需要将枚举引入到 A 之外的范围,则有一个不依赖于命名空间的解决方案。 与使用命名空间相反,A 和 A_Enum 都可以是嵌套类。

struct A_Enum
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };
};

struct A : public A_Enum
{
    using A_Enum::A_enum;
};

struct B : public::A_Enum
{
    using A_Enum::A_enum; // original enum name
    bool testA(A_enum val) { return (val == E1); }
};

EDIT2:再次删除了第二个解决方案,并不像我想象的那样工作。

It appears there isn't a simple solution. Bothers me too.
If you are allowed to change A there is a solution that doesn't depend on namespaces if inctoduction of the enum to a scope outside A is not desired. In contrast to using namespaces both A and A_Enum can be nested classes.

struct A_Enum
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };
};

struct A : public A_Enum
{
    using A_Enum::A_enum;
};

struct B : public::A_Enum
{
    using A_Enum::A_enum; // original enum name
    bool testA(A_enum val) { return (val == E1); }
};

EDIT2: removed second solution again, doesn't work as I thought.

绝不服输 2024-07-27 09:23:16
typedef enum ENUM_TYPE
{
  EN1 = 0,
  EN2,
  EN3
} ENUM_TYPE;

struct A 
{
  typedef enum ENUM_TYPE
  {
    EN1 = 0,
    EN2,
    EN3
  } ENUM_TYPE;  
}

struct B 
{
  typedef enum ENUM_TYPE
  {
    EN1 = 0,
    EN2,
    EN3
  } ENUM_TYPE;

  typedef ::ENUM_TYPE G_ENUM_TYPE;
  typedef A::ENUM_TYPE A_ENUM_TYPE;
  
  friend bool operator==(::ENUM_TYPE left, ENUM_TYPE right)
  {
    return left == (::ENUM_TYPE)right;
  }

  friend bool operator==(A::ENUM_TYPE left, ENUM_TYPE right)
  {
    return left == (A::ENUM_TYPE)right;
  }
    
}
typedef enum ENUM_TYPE
{
  EN1 = 0,
  EN2,
  EN3
} ENUM_TYPE;

struct A 
{
  typedef enum ENUM_TYPE
  {
    EN1 = 0,
    EN2,
    EN3
  } ENUM_TYPE;  
}

struct B 
{
  typedef enum ENUM_TYPE
  {
    EN1 = 0,
    EN2,
    EN3
  } ENUM_TYPE;

  typedef ::ENUM_TYPE G_ENUM_TYPE;
  typedef A::ENUM_TYPE A_ENUM_TYPE;
  
  friend bool operator==(::ENUM_TYPE left, ENUM_TYPE right)
  {
    return left == (::ENUM_TYPE)right;
  }

  friend bool operator==(A::ENUM_TYPE left, ENUM_TYPE right)
  {
    return left == (A::ENUM_TYPE)right;
  }
    
}
泛滥成性 2024-07-27 09:23:16

为什么你在 struct B 中有测试方法? 我认为这没有任何意义。

通过定义结构体 A 并在其中定义一个枚举,您或多或少是在说“这是结构体 A 范围内的一个枚举”,这与说“如果您想使用这个枚举,您必须引用结构A”。

将枚举放在名称空间内并不能解决您的问题。 因为你会遇到同样的范围问题(C4482),

我认为你让事情变得太复杂了。 你觉得这怎么样?

struct A
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };

    static bool test(A_enum val)
    {
        return (val == E1);
    }
};


int main()
{
    assert(A::test(A::E1));
    return 0;
}

请注意,A::test() 是静态的。 应该是因为您没有对结构状态进行操作。 由于它是静态的,因此您不需要 A 的实例来调用该方法。

Why do you even have the test method in struct B? I don't think it makes any sense.

By defining struct A and defining an enum inside it, you are more or less saying that "here's an enum in scope of struct A" and this is the same as saying "if you want to use this enum, you have to refer to the struct A".

Putting the enum inside a namespace will not solve your problem. Because you will have the same scope problem (C4482)

I think you are making things too complicated. What do you think of this?

struct A
{
    enum A_enum
    {
        E0,
        E1,
        E2
    };

    static bool test(A_enum val)
    {
        return (val == E1);
    }
};


int main()
{
    assert(A::test(A::E1));
    return 0;
}

Note that A::test() is static. It should be because you aren't operating on the struct state. And since it's static, you dont need an instance of A to call the method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文