5

この質問には少し説明が必要です。申し訳ありません。一部の C++ コードを解析する doxygen の見落としを修正していますが、doxygen が考慮していない珍しいコーナー ケースに遭遇しました。修正はありますが、より一般的なものにしたいので、説明が必要です。

doxygen が失敗するケースを説明するために、ザ・シンプソンズを含む不自然な例を定義します (これらのタイプの質問で一般的であるように思われるため)。次の列挙型があるとしましょう。

enum simpson { HOMER, MARGE, BART, LISA, MAGGIE };

次に、enum 値を (自然に 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

Cでは、、、またはの正規名にstructその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は列挙型であり、その時点では衝突はありません。2 番目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 された名前と関数名 (または同じスコープ内の変数名) の間で名前の衝突が発生します。

*ここでのhidesは、1 つのスコープ内の変数が外側のスコープ内の同じ名前の変数を隠しているという意味では使用されません。typedefC++ には、C と同様に、2 つの識別子スペースがあり、1 つはユーザー定義型用で、もう 1 つは-ed 型エイリアスを含むほとんどすべてのもの用です。C++ でのルックアップは、内側のスコープから外側のスコープまで実行され、各スコープでグローバル識別子スペースが検索されます。識別子が見つからない場合は、ユーザー定義型の識別子スペースで同じ識別子が検索されます。この最後のステップは、複雑な型指定子が常に必要な C では実行されません。それも失敗した場合にのみ、コンパイラは次のスコープに移動します。

于 2011-05-23T07:43:57.090 に答える
1

struct//classまたunion。標準では、「クラスキー識別子」で構成される「elaborated-type-specifier」については、3.4.4-1を参照してください。(BTW- switch case returnsの場合、その必要はありませんbreak。)

于 2011-05-23T02:28:34.827 に答える
1

あなたがしたことは、Cコーダーが一日中行うのと同じことです-ユーザー定義のタイプの前に適切なキーワードを付けます。struct、class、union、typedef、変数宣言、基本的にどこでも同じことが機能します。

于 2011-05-23T02:29:43.050 に答える