我最近遇到的问题是我需要一些辅助函数来返回不同类型的实例,类似于std::make_pair
。我选择的语法是:
Event event(Trigger(...), []() { });
其中...
是一个基于...
类型创建不同触发类型的简单参数(例如Time
,UserInput
等。)
此外,我想要一些可以直接使用的预定义触发器,例如:
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,但我想知道根据标准是否以及如何有效。两个编译器都支持这个“运气”吗?或者是否定义了名称查找,以确保它可以在所有编译器上运行?
答案 0 :(得分:1)
能够命名一个结构(或C ++中的类)类型与该结构的实例相同是从C引入的,这是因为结构名称在一个单独的命名空间中(不是C ++ {{ 1}}虽然)与变量名相比。
答案 1 :(得分:1)
在函数调用语法Trigger(...)
中,类按实例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
}
所以你的代码符合标准。 (它是否是一种好的风格完全是另一回事!)