C++对于哪些类型,参数类型名称可以与带有类型说明符的参数名称相同?
这个问题需要一些解释,抱歉。我正在修复 doxygen 解析某些 C++ 代码时的疏忽,并且遇到了 doxygen 无法解释的异常情况。我有一个修复程序,但我想让它更通用,所以我需要一些解释。
为了说明 doxygen 失败的情况,我将定义一个涉及《辛普森一家》的人为示例(因为这似乎在此类问题中很受欢迎)。假设我们有以下枚举:
enum simpson { HOMER, MARGE, BART, LISA, MAGGIE };
现在我们想要将枚举值传递到一个方法(自然是 Simpsons 类的),如下所示:
const char* voicedBy(simpson simpson)
{
switch (simpson) {
case HOMER:
return "Dan Castellaneta";
case MARGE:
return "Julie Kavner";
case BART:
return "Nancy Cartwright";
case LISA:
return "Yeardley Smith";
case MAGGIE:
return "*suck* *suck*";
}
}
不幸的是,这会产生编译器错误,因为不允许使用枚举类型 'simpson'与参数名称“simpson”相同(与 C# 等不同)。但是,C++ 对此有一个答案。您可以将 enum 关键字放在类型名称前面,如下所示:
const char* voicedBy(enum simpson simpson)
现在代码将编译并运行。不幸的是 doxygen 没有考虑这种情况,因此它将整个字符串“enum simpson simpson”视为没有参数名称的参数类型。我想出了一些代码来修复 doxygen 在像上面这样的枚举的情况下。
我的问题是,这种技巧还适用于哪些其他类型?结构?,联合?,typedef?,其他?就此而言,“与参数名称同名的方法参数的类型说明符”概念是否有一个名称,以便我可以获得更多详细信息?
This question is going to take a bit of explination, sorry. I am fixing an oversight in doxygen parsing some C++ code and I have come across an unusual corner case that doxygen doesn't account for. I have a fix but I want to make it more general so I need some explanation.
To illustrate the case where doxygen is failing I am going to define a contrived example involving The Simpsons (because that seems to be popular for these types of questions). Let's say that we have the following enum:
enum simpson { HOMER, MARGE, BART, LISA, MAGGIE };
Now we want to pass the enum value into a method (of the Simpsons class naturally) that looks like this:
const char* voicedBy(simpson simpson)
{
switch (simpson) {
case HOMER:
return "Dan Castellaneta";
case MARGE:
return "Julie Kavner";
case BART:
return "Nancy Cartwright";
case LISA:
return "Yeardley Smith";
case MAGGIE:
return "*suck* *suck*";
}
}
Unfortunately this produces a compiler error because the enum type 'simpson' is not allowed to be the same as the parameter name 'simpson' (Unlike in, say, C#). But, C++ has an answer to this. You put the enum keyword in front of the type name like this:
const char* voicedBy(enum simpson simpson)
and the code will now compile and run. Unfortunately doxygen doesn't account for this case and so it treats the entire string "enum simpson simpson" as a parameter type with no parameter name. I have come up with some code to fix doxygen in the case of an enum like above.
My question is, what other types is this kind of trick valid for? struct?, union?, typedef?, others? And for that matter, does the 'type specifier for method parameter with same name as parameter name' concept have a name so that I can get some more details on it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您使用什么编译器和版本?
不存在
enum
,也就是说,您不需要在此上下文中使用详细的类型说明符,并且它可以在 gcc 4.2 和 4.6 中完美编译。问题在于,在函数内部,参数名称隐藏了*类型,并且如果您想在内部声明具有该类型的新变量在该范围内,您将需要详细的类型说明符,但在函数签名中,它是从左到右解析的,这意味着第一个 simpson 是枚举,此时不会发生冲突。第二个simpson
引入了本地名称,从那里开始,simpson
指的是参数而不是类型。如果您定义一个与所需类型同名的函数,则可能会发生相同类型的名称隐藏:
请注意,如果您添加 typedef,则在最后一种情况下情况会发生一些变化: typedef 名称和函数名称(或同一范围内的变量名称)之间的名称冲突。
* 这里的 hides 并不是指一个作用域中的变量隐藏外部作用域中同名的变量。在 C++ 中,就像在 C 中一样,有两个标识符空间,一个用于用户定义的类型,另一个用于大多数其他内容,包括
typedef
-ed 类型别名。 C++中的查找是从内部作用域到外部作用域进行的,在每个作用域中搜索全局标识符空间,如果没有找到标识符,则在用户定义类型标识符空间中搜索相同的标识符。最后一步在 C 中不执行,因为 C 中始终需要详细的类型说明符。仅当这也失败时,编译器才会移至下一个作用域。What compiler and version are you using?
No
enum
present, that is, you don't need to use an elaborated type specifier in this context, and it compiles perfectly in gcc 4.2 and 4.6. The problem is that inside the function, the argument name hides* the type, and if you want to declare a new variable with that type inside that scope you will need the elaborated type specifier, but in the function signature it is parsed left to right, and that means that the firstsimpson
is the enum and at that time there is no collision. The secondsimpson
introduces a local name, and from there on,simpson
refers to the parameter and not the type.The same type of name hiding can happen if you define a function with the same name as the type you want:
Note that if you add a typedef the things change a little in this last case: there will be a name clash between the typedef-ed name and the function name (or a variable name in the same scope).
* Here hides is not used in the sense of a variable in one scope hiding a variable with the same name in an outer scope. In C++, as in C, there are two identifier spaces, one for user defined types, and another for mostly everything else including
typedef
-ed type aliases. Lookup in C++ is performed from the inner scope to the outer scope, and in each scope the global identifier space is searched, if the identifier is not found, then the user defined types identifier space is searched for the same identifier. This last step is not performed in C, where elaborated type specifiers are required always. Only if that also fails, the compiler will move to the next scope.在 C 中,
struct
、union
或enum
的规范名称包含该前缀:这是创建
习惯用法的来源 。删除前缀的 code>typedef
名称:C++ 也有此功能,
class
也具有相同的行为,template
和template
也具有类似的行为模板中的代码>类型名称。但是,它还删除了包含前缀的要求,除非在不明确的情况下。我不认为这个概念有名字,但我的观点是正确的:它是一个详细的类型说明符。一个合适的解决方法可能是将 Doxygen 注释放在声明而不是定义上。
In C, the canonical name of a
struct
,union
, orenum
includes that prefix:Which is the source of the idiom of creating a
typedef
name with the prefix removed:C++ has this as well, with the same behaviour also given to
class
, and analogous behaviour given totemplate
andtypename
in templates. However, it also removes the requirement of including the prefix except in ambiguous cases.I didn't think this concept had a name, but I stand corrected: it's an elaborated type specifier. A suitable workaround for this may be to place the Doxygen comments on the declaration rather than the definition.
您在那里所做的与 C 编码员整天所做的事情相同 - 使用适当的关键字为用户定义的类型添加前缀。这同样适用于结构、类、联合、typedef、变量声明,基本上任何地方。
What you did there is the same thing C coders do all day - prefixing their user defined types with the appropriate keyword. The same works for struct, class, union, in typedefs, variable declarations, anywhere basically.
也有
struct
/class
/union
。在标准中,“详细类型说明符”由“类键标识符”组成,见 3.4.4-1。 (顺便说一句 - 如果switch
case
返回
,则无需break
。)struct
/class
/union
also. In the Standard, "elaborated-type-specifier"s, consisting of "class-key identifier", see 3.4.4-1. (BTW - if aswitch
case
return
s, it has no need tobreak
.)