A“使用” 带有枚举的声明

发布于 2024-07-11 07:59:42 字数 276 浏览 9 评论 0原文

using 声明似乎不适用于枚举类型:

class Sample{
    public:
        enum Colour {RED, BLUE, GREEN};
}

using Sample::Colour;

不起作用!

我们是否需要为每个枚举类型的枚举器添加一个 using 声明? 就像下面这样:

using sample::Colour::RED;

A using declaration does not seem to work with an enum type:

class Sample{
    public:
        enum Colour {RED, BLUE, GREEN};
}

using Sample::Colour;

does not work!

Do we need to add a using declaration for every enumerators of enum type? Like below:

using sample::Colour::RED;

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

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

发布评论

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

评论(4

满天都是小星星 2024-07-18 07:59:42

要添加到 Steve Lacey 的答案,原始代码的问题是您引用一个成员,但 using 声明本身并不是一个成员声明:

7.3.3/6 有:

类成员的使用声明
应是成员声明。

为了强调这一点,以下示例确实有效:

class Sample
{
public:
  enum Colour { RED,BLUE,GREEN};
};

class Derived : public Sample
{
public:
  using Sample::Colour;  // OK
};

最后,正如 Igor Semenov 指出的那样: ,即使您将枚举定义移动到命名空间中,从而允许 using 声明,using 声明也只会将枚举类型的名称声明到命名空间中(2003标准参考为 7.3.3/2)。

namespace Sample
{
  enum Colour { RED,BLUE,GREEN};
}

using Sample::Colour;
using Sample::BLUE;


void foo ()
{
  int j = BLUE; // OK
  int i = RED;  // ERROR
}

依赖基类型

当编译器解析类模板时,允许部分和显式特化。 它不会在依赖基类中执行任何查找。 因此,以 Sample 作为模板的以下变体无法编译:

template <typename T>
class Sample
{
public:
  enum Colour { RED,BLUE,GREEN};
};

template <typename T>
class Derived : public Sample<T>
{
public:
  using Sample<T>::Colour;  // What kind of entity is Colour?

  Colour foo ()     // Not OK!
  {
  return this->RED;
  }
};

问题是 Derived::Colour 被编译器视为对象 (14.6/2):

假定模板声明或定义中使用的且依赖于模板参数的名称不会命名类型,除非适用的名称查找找到类型名称或该名称由关键字 typename 限定。

查看名称成为类型的两个条件:

  1. 查找 Colour 未找到类型,因为未搜索依赖的基 Sample
  2. 该名称未通过 typename 限定,

因此该示例需要 typename 关键字:

template <typename T>
class Derived : public Sample<T>
{
public:
  using typename Sample<T>::Colour;  // Colour is treated as a typedef-name

  Colour foo ()  // OK
  {
  return this->RED;
  }
};

注意: 1998 版本的标准不允许 typename 与 using 声明一起使用,因此上述修复是不可能的。 请参阅从依赖基类访问类型CWG11

To add to Steve Lacey's answer, the problem with the original code is that you refer to a member, but the using declaration is not itself a member declaration:

7.3.3/6 has:

A using-declaration for a class member
shall be a member-declaration.

To highlight this, the following example does work:

class Sample
{
public:
  enum Colour { RED,BLUE,GREEN};
};

class Derived : public Sample
{
public:
  using Sample::Colour;  // OK
};

Finally, as pointed out by Igor Semenov, even if you move the enum definition into a namespace, thereby allowing the using declaration, the using declaration will only declare the name of the enum type into the namespace (the 2003 standard reference is 7.3.3/2).

namespace Sample
{
  enum Colour { RED,BLUE,GREEN};
}

using Sample::Colour;
using Sample::BLUE;


void foo ()
{
  int j = BLUE; // OK
  int i = RED;  // ERROR
}

Dependent Base Types

To allow for partial and explicit specializations, when the compiler parses a class template. it does not perform any lookups in dependent base classes. As a result, the following variation with Sample as a template does not compile:

template <typename T>
class Sample
{
public:
  enum Colour { RED,BLUE,GREEN};
};

template <typename T>
class Derived : public Sample<T>
{
public:
  using Sample<T>::Colour;  // What kind of entity is Colour?

  Colour foo ()     // Not OK!
  {
  return this->RED;
  }
};

The problem is that Derived::Colour is treated as an object by the compiler (14.6/2):

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

Looking at the two conditions for the name to be a type:

  1. Lookup for Colour doesn't find a type because the dependent base Sample<T> is not searched.
  2. The name is not qualified by typename

The example therefore needs the typename keyword:

template <typename T>
class Derived : public Sample<T>
{
public:
  using typename Sample<T>::Colour;  // Colour is treated as a typedef-name

  Colour foo ()  // OK
  {
  return this->RED;
  }
};

Note: The 1998 version of the standard didn't allow typename to be used with a using declaration and so the above fix was not possible. See Accessing types from dependent base classes and CWG11.

终陌 2024-07-18 07:59:42

类没有定义名称空间,因此“使用”在这里不适用。

另外,您需要公开枚举。

如果您尝试在同一个类中使用枚举,请参阅以下示例:

class Sample {
 public:
  enum Colour { RED, BLUE, GREEN };

  void foo();
}

void Sample::foo() {
  Colour foo = RED;
}

并从类外部访问它:

void bar() {
  Sample::Colour colour = Sample::RED;
}

A class does not define a namespace, and therefore "using" isn't applicable here.

Also, you need to make the enum public.

If you're trying to use the enum within the same class, here's an example:

class Sample {
 public:
  enum Colour { RED, BLUE, GREEN };

  void foo();
}

void Sample::foo() {
  Colour foo = RED;
}

And to access it from outside the class:

void bar() {
  Sample::Colour colour = Sample::RED;
}
苦笑流年记忆 2024-07-18 07:59:42

C++ 标准,7.3.3.1:

在a中指定的成员名称
using-声明是在
声明区域,其中
出现 using 声明。 [ 笔记:
只有指定的名字是这样
宣布; 指定一个枚举
using 声明中的名称不
在中声明其枚举器
using-declaration 的声明式
地区。 ——尾注]

C++ Standard, 7.3.3.1:

The member name specified in a
using-declaration is declared in the
declarative region in which the
using-declaration appears. [ Note:
only the specified name is so
declared; specifying an enumeration
name in a using-declaration does not
declare its enumerators in the
using-declaration’s declarative
region. —end note ]

千柳 2024-07-18 07:59:42

现在,有一个相关的问题: 'using enum' in C++ 20

看起来 C++20 将可以选择使用 using enum 声明,从而最终允许直接访问枚举类的成员,如下所示 (source):

enum class fruit {
    orange,
    apple,
};

struct S {
  using enum fruit;             // OK, introduces orange and apple into S
};
void f() {
  S s;
  s.orange;                     // OK, names fruit​::​orange
  S::orange;                    // OK, names fruit​::​orange
}

当然,这意味着在 S 内部,您也可以简单地使用 orangeapple 而不是 fruit::orangefruit::apple

By now, there's a related question: 'using enum' in C++20.

It looks like C++20 will have the option make a using enum declaration, thus finally allowing direct access to an enum class' members, like this (source):

enum class fruit {
    orange,
    apple,
};

struct S {
  using enum fruit;             // OK, introduces orange and apple into S
};
void f() {
  S s;
  s.orange;                     // OK, names fruit​::​orange
  S::orange;                    // OK, names fruit​::​orange
}

Of course, that means that inside S, you will also be able to simply use orange and apple instead of fruit::orange and fruit::apple.

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