web-dev-qa-db-ja.com

C ++でno-opステートメントを実装する移植可能な方法は何ですか?

C++で何もしないステートメントが必要になる場合があります。たとえば、非デバッグ構成で無効になっているassert()を実装する場合( この質問 も参照):

#ifdef _DEBUG
#define assert(x) if( !x ) { \
                     ThrowExcepion(__FILE__, __LINE__);\
                  } else {\
                     //noop here \
                  }
#else
#define assert(x) //noop here
#endif

これまでのところ、何もしないのに(void)0;を使用するのが正しい方法であるという印象を受けています。

(void)0;

ただし、一部のコンパイラでは警告が表示される可能性があると思います。C4555: expression has no effect; expected expression with side-effect Visual C++の警告のように、この特定のケースでは出力されませんが、voidへのキャストがない場合に出力されます。

普遍的にポータブルですか?もっと良い方法はありますか?

28
sharptooth

一部のコンパイラで警告をトリガーする可能性があると思います

おそらく、((void)0)は、assertが定義されている場合に標準のNDEBUGマクロが展開されるものであるためです。したがって、警告を発行するコンパイラは、アサートを含むコードがリリース用にコンパイルされるたびに警告を発行します。これはユーザーのバグと考えられます。

コンパイラは、(void)0だけを特別に扱いながら、提案((void)0)を警告することでその問題を回避できると思います。したがって、((void)0)を使用した方がよいかもしれませんが、私はそれを疑っています。

一般的に、囲み括弧の有無にかかわらず、何かをvoidにキャストすることは、慣例的に「これを無視する」ことを意味します。たとえば、未使用の変数に対する警告を抑制するために関数パラメーターをvoidにキャストするCコードで。したがって、そのスコアについても、警告を抑制しても別の警告が表示されるだけなので、警告を出したコンパイラはあまり人気がありません。

C++では、標準ヘッダーは相互に含めることが許可されていることに注意してください。したがって、any標準ヘッダーを使用している場合は、assertが定義されている可能性があります。そのため、そのコードはそのアカウントでは移植できません。 「ユニバーサルポータブル」について話している場合は、通常、標準ヘッダーで定義されているマクロを予約済み識別子として扱う必要があります。あなたはcould定義を解除しますが、独自のアサーションに別の名前を使用する方が賢明でしょう。私はそれが単なる例であることを知っていますが、すべてのC++実装にすでにassertが「ユニバーサルに移植可能な」方法で定義する必要がある理由はわかりません。ここで行うように定義しています。

15
Steve Jessop

最も単純なno-opは、コードがまったくないことです。

#define noop

次に、ユーザーコードは次のようになります。

if (condition) noop; else do_something();

あなたが言及する代替案も何もしません:(void)0;、ただし、マクロ内で使用する場合は、;発信者が追加するために脇に:

#define noop (void)0
if (condition) noop; else do_something();

;はマクロの一部だったので、余分な; そこ)

do { } while(0)はどうですか?はい、それはコードを追加しますが、今日のほとんどのコンパイラはそれを最適化できると確信しています。

;標準の無操作と見なされます。コンパイラがコードを生成しない可能性があることに注意してください。

5
ziu

そして何について:

#define NOP() ({(void)0;})

あるいは単に

#define NOP() ({;})

ここでの目的、およびマクロを何も定義しない理由は、requireユーザーに_;_を追加することです。そのためには、statementが合法であれば、どこでも_(void)0_(または_((void)0)_、またはその他のバリエーション)で問題ありません。

globalスコープで同じことをする必要があるため、この質問を見つけました。幸い、C++ 11は代替手段static_assert(true, "NO OP")を提供します。これはanywhereを使用でき、マクロの後に_;_を要求するという私の目的を達成します。 (私の場合、マクロはソースファイルを解析するコード生成ツールのタグなので、コードをC++としてコンパイルするとalwaysはNO-OPになります。)

1
Matthew

私の知る限り、それは普遍的に移植可能です。

#define MYDEFINE()

同様に行います。

別のオプションは次のようなものかもしれません:

void noop(...) {}
#define MYDEFINE() noop()

ただし、私は(void)0に固執するか、または __ noop のような組み込み関数を使用します

0
mloskot
    inline void noop( ) {}

自己文書化

0
gerardw

私は以下を使用することをお勧めします:

static_cast<void> (0)   
0
MattP

このコードは最適化によって省略されません

static void nop_func()  {   }
typedef void (*nop_func_t)();
static nop_func_t nop = &nop_func;

for (...)
{
    nop();
}
0
iperov