【问题标题】:How to write a 'using' statement for enum classes? [duplicate]如何为枚举类编写“使用”语句? [复制]
【发布时间】:2013-06-03 04:37:10
【问题描述】:

在我正在编写的石头剪刀布程序中,我列举了三个不同的动作并将它们声明为一个类。但是,当我尝试编写 using 语句以避免使用范围运算符时,它似乎不起作用。有人知道为什么吗?

enum class choice {rock, paper, scissors};

using namespace choice;

这里出现一条错误消息,说:[Error] 'choice' 不是命名空间名称。 为什么是这样?在这种情况下,我认为 for 选择可能是一个命名空间。

【问题讨论】:

    标签: c++ class namespaces enumeration using


    【解决方案1】:

    我会做一些类似于 Lut_99 的事情(但略有不同):

    namespace choice_ns {
    enum Choice { rock, paper, scissors };
    }
    using choice_ns::Choice;
    
    bool beats(Choice a, Choice b) {
      using namespace choice_ns;
      switch (a) {
        case rock:
      // etc...
    }
    
    void does_not_compile() {
      rock;  // This requires qualification.
    }
    

    请注意,enum class 没有被使用,但可以达到类似的效果:在说 rock 时,您必须使用 choice_ns:: 前缀。这样可以避免污染外部命名空间,这是enum class 的重点。另请注意,与enum class 一样,您可以引用Choice 而不使用choice_ns:: 前缀。

    命名空间的名称故意让人感到尴尬,因为你唯一需要它的时候是在函数开头说using namespace ...

    这和 Lut_99 建议的一个区别是,如果你按照他的方式做,声明看起来像这样:

    choice::type a;
    

    与我的方式相比,这既冗长又尴尬:

    Choice a;
    

    其他一些建议涉及做

    constexpr SomeType rock = whatever::rock;
    

    但这真的不是很好,因为重复,这意味着你很有可能会犯错误,特别是如果你决定稍后添加值。例如。 https://www.youtube.com/watch?v=Kov2G0GouBw

    我想要这个已经有一段时间了。很高兴从 Baptistou 看到,这将在不久的将来成为可能。同时,您可以使用当今可用的技术获得非常相似的东西。

    【讨论】:

      【解决方案2】:
      namespace choice
      {
          enum class type {rock, paper, scissors};
          constexpr auto rock     = type::rock    ;
          constexpr auto paper    = type::paper   ;
          constexpr auto scissors = type::scissors;
      }
      
      int main()
      {
          choice::type move;
          using namespace choice;
          move = rock;
          move = paper;
          move = scissors;
      
          return 0;
      }
      

      【讨论】:

        【解决方案3】:

        这可能是一个非常古老的问题,但是为了扩展@catscradle 的答案和@anton_rh 的评论,如果您添加一个“使用”语句来为选择创建快捷方式::选择:

        namespace choice_values {
            enum type {
                rock,
                paper,
                scissors
            }
        }
        using choice = choice_values::type;
        

        现在,你可以正常使用枚举了:

        choice chosen_move = choice::rock;
        

        但如果您使用choice_values 命名空间,您也可以避免使用范围运算符:

        using namespace choice_values;
        choice chosen_move = rock;
        

        (我知道作为评论可能会更好,但我还没有这样做的声誉......)

        【讨论】:

        • 您的解决方案适用于普通枚举,而不是问题指定的 class 枚举。因此(我假设)反对票。
        • @phlummox 这不是投反对票的好理由,因为枚举类的目的是避免污染,但 Lut_99 的建议也实现了这一目标。
        • @allyourcode 我不确定你为什么要回应我从未说过的事情。我从来没有说过这是一个很好的理由。我说我认为这可能就是它被否决的原因。碰巧的是,我没有对此投反对票。但再看一遍,也许我应该。
        【解决方案4】:

        这将在 C++20 中成为可能,P1099R5

        enum class choice {rock, paper, scissors};
        
        using enum choice;
        

        【讨论】:

          【解决方案5】:

          如果像下面这样,我只使用“typedef A::B::C C”。

          namespace A
          {
              class B
              {
              public:
                  enum class C : unsigned char
                  {
                      Something
                  };
              };
          }
          

          【讨论】:

            【解决方案6】:

            您想要的行为可以通过namespace choice { enum choice { ... }; } 实现。虽然它只适用于值,但如果你想声明一个变量,你仍然必须使用choice::choice。当然,除非你也使用auto

            【讨论】:

            • namespace choice { enum type { ... }; },然后是choice::type move = choice::rock;
            【解决方案7】:
            enum class choice {rock, paper, scissors}
            rock = choice::rock, paper = choice::paper, scissors = choice::scissors;
            

            【讨论】:

            【解决方案8】:

            choice 不是命名空间,因此using namespace choice; 无效。如果您不想使用范围指示符,请不要使用范围枚举。一个普通的枚举将适用于您到目前为止提到的内容:

            enum choice { rock, paper, scissors };
            

            【讨论】:

            • hmm... 你听说过 brian overland 的C++ without Fear一书吗?在那里,他声称可以使用命名空间。也许我做错了什么。有什么方法可以避免在声明范围枚举的同时避免使用范围运算符?
            • @user2457666 如果您真的想使用范围运算符,请将enum 放入namespace
            • 如果您在命名空间内使用常规 enum(有效地使用 C++11 之前的功能重新创建 enum class 的“具有自己的范围”部分),那么 using namespace 将起作用.不过,这确实失去了enum class 的其他好处,即增加的类型安全性(以及在较小程度上明确指定的底层类型(或默认情况下为int),但这也适用于普通enums在 C++11 中(只是没有明确的“如果未指定,则默认为 int”)。
            猜你喜欢
            • 2015-06-16
            • 2016-04-22
            • 2021-12-19
            • 1970-01-01
            • 2020-07-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多