2011-07-27 1 views
6

C++標準に基づいて以下のような法律が適用されますか? (答えは標準に標準と異なる場合は、私はあまりにも、それを知っていると思います。)目標は、私がトップレベルで呼び出し、セミコロンに従うことができますマクロを定義することであるトップレベルのno-opをC++で定義していますか?

#define VERY_OLD_COMPILER 1 

#ifdef VERY_OLD_COMPILER 
#define USING_NAMESPACE_STD enum { } 
#else 
#define USING_NAMESPACE_STD using namespace std 
#endif 

USING_NAMESPACE_STD; 

int main(int argc, char *argv[]) { 
// etc. 

、それは効果がないように。私は、トップレベルの迷惑セミコロンが許可されていないことを確信しています(GCCは、とにかくそれについて不平を言います)。単に空のマクロを定義するだけではうまくいきません。

空の匿名構造体を宣言すると、名前が必要なため、名前空間を汚染したくないため、機能しません。

匿名の空の列挙宣言(enum { })がこのトリックを行いますか?私が試したすべてのコンパイラで動作しますが、もちろんそれは仕様で許可されているものと同じではありません。

他のアイデアやコメントを歓迎します。まあ、 "コンパイラを投げる"以外の何か。私を信じて、私はしたいです。

+6

セミコロンでマクロ呼び出しを続けなければならないのはなぜですか?あなたがそれをやっていないなら、これは解決するのが簡単ではないでしょうか? –

+1

@Greg:個人的な好み。私は関数内で 'DO_STUFF(x、y);'のようなマクロを呼び出すことに慣れています、そして、私はそのようなノーオペレーションを書く方法を知っています。私は 'USING_NAMESPACE_STD'はこれの良い名前だと思うし、最後にセミコロンを置くと自然に見えるので、それは私が望むものだと思う。私はそれが仕様で定義されている言語で可能かどうか不思議です。 – Nemo

+1

私は、末尾のセミコロンを好むことに同意するでしょう。セミコロンの後に続かないステートメントのようなマクロを使用する必要がある場合がありますが、それを避けることができる場合は、そうする必要があります。 –

答えて

6

最新のパブリックC++ 0xドラフトを見ると、トップレベルのセミコロンが許可され無視されているようです。

文法は、declarationのシーケンスとしてtranslation-unitを処理します。さまざまな種類の宣言の中には、単純なセミコロンであるempty-declarationがあります。

実用的なソリューション:あなたVERY_OLD_COMPILER定数は全部が古いコンパイラの回避策の一部であることがあることを示唆していることを考えると、私は、このコンパイラで動作するソリューションを選ぶだろう、それが標準化されるかどうか。宣言するときに、オプションのinit-宣言子リストのみを省略することができる単純な宣言において

7/3宣言:

+0

実際、新しいGCCでは、セミコロンの迷子に気をつけていないようです。また、1つのコンパイラで作業するだけの良い点もあります。仕様を掘り下げてくれてありがとう。 – Nemo

2

Comeauには言いません:

> Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for 
> ONLINE_EVALUATION_BETA2 Copyright 1988-2008 Comeau Computing. All 
> rights reserved. MODE:strict errors C++ C++0x_extensions 
> 
> "ComeauTest.c", line 1: error: declaration does not declare anything 
> enum { }; ^
> 
> 1 error detected in the compilation of "ComeauTest.c". 

あなたは

#define USING_NAMESPACE_STD struct very_long_name_that_i_hope_doesnt_collide_because_if_it_does_oh_noes 
+0

+1良い情報がありますが、スペックの章と節を引用すると回答を受け入れる可能性が高くなります。 – Nemo

0
#define VERY_OLD_COMPILER 1 

#ifdef VERY_OLD_COMPILER 
#define USING_NAMESPACE_STD typedef unsigned long uint32 
#else 
#define USING_NAMESPACE_STD using namespace std 
#endif 

USING_NAMESPACE_STD; 

編集使用することができます。また、これは動作するはず を:

#define VERY_OLD_COMPILER 1 

#ifdef VERY_OLD_COMPILER 
#define USING_NAMESPACE_STD double fabs(double) 
#else 
#define USING_NAMESPACE_STD using namespace std 
#endif 

USING_NAMESPACE_STD; 
+0

私が言及したように、迷子セミコロンは違法であるため、これは機能しません。 – Nemo

+0

申し訳ありませんが、私のgccはそれについて不平を言っていませんでした。 typedefソリューションをお試しください。 –

+0

'int main();'は良くありませんC++。 Cとは異なり、 "指定されていない引数"を意味するC++では、引数がないことを意味し、エラーが発生する可能性があります。 –

4
#define USING_NAMESPACE_STD static int dummy##__LINE__ 
+0

関数 "dummy13"の名前を決める貧しいプログラマー?私は80個のランダムな文字を選ぶ方が良いかもしれません...名前空間を汚染することなくこれを行う方法は本当にありますか? – Nemo

0

申し訳ありませんが、あなたはトップレベルで行う必要があることを忘れていました。

どの程度

extern int _; 

?私はどのような望ましくない副作用があるのか​​分かりませんが、私は考えることはできません。

4

空の列挙は、C++ 03によれば、実際には違法ですdecl-specifier-seqがクラス指定子、クラスキー(9.1)を持つ精巧な型指定子、またはenum指定子のいずれかを含んでいる場合、クラス(9節)または列挙(7.2)これらの場合、およびクラス指定子またはenum指定子がdecl-specifier-seqに存在するときはいつでも、これらの指定子の識別子は、宣言によって宣言された名前の中にあります(クラス名、列挙名または列挙子、構文に応じて)。そのような場合、名前のないビットフィールド(9.6)の宣言を除いて、decl-specifier-seq は、プログラムに1つ以上の名前を導入するか、前の宣言によって導入された名前を再宣言するものとする。

[Example: 
enum { }; // ill-formed 
typedef class { }; // ill-formed 
—end example] 

だから私はダミーenumstruct前方宣言、または明らかに(良い測定のためにそこにGUIDを投げる)何と競合するつもりはない名前のtypedef宣言を宣言するMSN's answerに同意するだろう。これらのことの素晴らしい点は、宣言を複数回表示させることができ、以前と同じであれば何の問題もないことです。

+0

申し訳ありませんが、私は1つの答えしか受け入れられません。 (それは私が2つの質問をするために得るものです。) – Nemo

0
#define VERY_OLD_COMPILER 1 

#ifdef VERY_OLD_COMPILER 
#define USING_NAMESPACE_STD ; 
#else 
#define USING_NAMESPACE_STD using namespace std 
#endif 

USING_NAMESPACE_STD; 

int main(int argc, char *argv[]) { 
// etc. 
関連する問題