相同的类和实例名称

Identical class and instance names

本文关键字:实例      更新时间:2023-10-16

我最近遇到了一个问题,即我需要一些辅助功能才能返回不同类型的实例,类似于 std::make_pair。我选择的语法是:

Event event(Trigger(...), []() { });

其中...是一些简单的参数,该参数基于...的类型创建了不同的触发类型(例如TimeUserInput等)。

此外,我想要一些可以直接使用的预定义触发器,例如:

Event event(Trigger::OnInit, []() { });

我发现定义一个名为Trigger的类和实例允许我支持这两个语法:

static const struct Trigger {
    static const OnceTrigger OnInit;
    TimeTrigger operator()(Time const &) const;
    UserTrigger operator()(UserInput const &) const;
} Trigger;

注意相同命名的类型和实例名称。

这在GCC和MSVC中都起作用,但是我想知道这是否按照标准有效。两个编译器都支持这一点是"运气"吗?还是定义了名称查找,以确保这可以在所有编译器上使用?

在函数调用语法Trigger(...)中,该类是由实例Per 3.3.10隐藏的:

2-类名称(9.1)或枚举名称(7.2)可以通过在同一范围中声明的变量,数据成员,功能或枚举器的名称隐藏。如果类或枚举名称和变量,数据成员,功能或枚举者以相同名称的同一范围(以任何顺序)声明,则类或枚举名称在变量,数据成员,功能或枚举的情况下隐藏枚举名称可见。

在合格的名称查找语法Trigger::OnInit中,该类可见每个3.4.3:

1 - [...]查找[] ::之前的名称,仅考虑其专业是类型的名称空间,类型和模板。

的确,该标准有一个示例,该示例说明了合格的名称查找不受类型名称隐藏的约束:

class A {
public:
  static int n;
};
int main() {
  int A;
  A::n = 42; // OK
  A b; // ill-formed: A does not name a type
}

因此,根据标准,您的代码很好。(这是否是一个好风格是另一回事!)

能够命名结构(或C 中的类)类型与该结构的实例相同,而从C中引入了该结构,这是因为结构名称在一个单独的名称空间中(与变量名相比,不是C namespace的意义。