5

这个问题需要解释一下,抱歉。我正在修复 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。

我的问题是,这种技巧适用于哪些其他类型?struct?、union?、typedef?、其他?就此而言,“与参数名称同名的方法参数的类型说明符”概念是否有名称,以便我可以获得更多详细信息?

4

4 回答 4

3

struct在 C 中, a 、union或的规范名称enum包含该前缀:

struct Point {
    int x, y;
};

enum Type {
    FIRST, SECOND, THIRD
};

struct Point p;
enum Type t;

typedef这是删除前缀创建名称的成语的来源:

typedef struct Point {
    int x, y;
} Point;

typedef enum Type {
    FIRST, SECOND, THIRD
} Type;

struct Point p;
enum Type t;
Point p;
Type t;

C++ 也有这一点,同样的行为也被赋予class,并且类似的行为被赋予模板templatetypename模板。但是,除了不明确的情况外,它还删除了包含前缀的要求。

我不认为这个概念有名字,但我的立场是正确的:它是一个详细的类型说明符。一个合适的解决方法可能是将 Doxygen 注释放在声明而不是定义上。

于 2011-05-23T02:28:55.217 回答
3

您使用的是什么编译器和版本?

void foo( simpson simpson ) {}

enum存在,也就是说,您不需要在此上下文中使用详细的类型说明符,并且它在 gcc 4.2 和 4.6 中完美编译。问题是在函数内部,参数名称隐藏类型,如果你想在该范围声明一个具有该类型的新变量,你将需要详细的类型说明符,但在函数签名中它是从左到右解析的,这意味着第一个simpson是枚举,当时没有冲突。第二个simpson引入了本地名称,从那里开始,simpson指的是参数而不是类型。

void relationship( /*enum*/ simpson simpson, enum simpson other = HOMER );
//                   ^^^^ optional           ^^^^ required
{
   enum simpson yet_another = simpson;
// ^^^^ required              ^^^^^^^ first argument!
}

如果您定义一个与您想要的类型具有相同名称的函数,则可能会发生相同类型的名称隐藏:

void simpson();
void voicedBy( enum simpson s );
//             ^^^^ required

请注意,如果您添加 typedef,则在最后一种情况下会发生一些变化:typedef-ed 名称和函数名称(或同一范围内的变量名称)之间会有名称冲突。

*这里的hides不是在一个范围内的变量隐藏外部范围内的同名变量的意义上使用的。在 C++ 中,与在 C 中一样,有两个标识符空间,一个用于用户定义类型,另一个用于几乎所有其他内容,包括typedef-ed 类型别名。C++中的查找是从内部作用域到外部作用域进行的,并且在每个作用域中搜索全局标识符空间,如果没有找到该标识符,则在用户定义类型标识符空间中搜索相同的标识符。最后一步不在 C 中执行,C 中始终需要详细的类型说明符。只有当这也失败时,编译器才会移动到下一个作用域。

于 2011-05-23T07:43:57.090 回答
1

struct//也classunion在标准中,“详细类型说明符”由“类键标识符”组成,见 3.4.4-1。(顺便说一句 - 如果是switch case returns,则无需break。)

于 2011-05-23T02:28:34.827 回答
1

您在那里所做的事情与 C 编码人员整天做的事情相同——在他们的用户定义类型前面加上适当的关键字。这同样适用于结构、类、联合、类型定义、变量声明,基本上任何地方。

于 2011-05-23T02:29:43.050 回答