2017-03-02 23 views
0

私はコード全体に散在する関数を持っています。これは開発に使用されますが、私は最終的なシステムで実行したくありません。これを行う1つの方法は、マクロである:C++空の実装で関数を選択的に置き換える方法

#if SPEAK_ENABLED 
    #define speak(m) implementation(m) 
#else 
    #define speak(m) ((void)0) 
#endif 

これはうまく動作しますが、私は同様の動作を取得するために使用することができます(おそらく、テンプレートを使用して)他のメカニズムがあります場合、私は思っていました。

私が試したことは、関数を宣言してから、すべてのメイン.cppファイルに実装を提供することでした。

enable.h:

void speak() 
{ 
     std::cout << "Output enabled" << std::endl; 
} 

disable.h:

void speak() 
{ 
} 

silent_main.h:

#include "disable.h" 

int main(int argc, char *argv[]) 
{ 
     speak(); 
     return 0; 
} 

talking_main.h:

#include "enable.h" 

int main(int argc, char *argv[]) 
{ 
     speak(); 
     return 0; 
} 
例えば

これは上記のような単純なケースで機能しますが、リンクされているときに関数の定義が不足していると不平を言うため、ライブラリでは機能しません。

これは基本的に私の使用例です。私は1つの実行可能なターゲットに対してこの機能を無効にしたいが、他のすべてのターゲットに対しては有効にしたい。

これは、マクロを使用することが正当な理由の1つですか?

+0

あなたのマクロの例は実際には間違っています - '#if'ブランチでは、拡張コマンドをセミコロンで終了してはならず、'#else'ブランチではノーオペレーション '((void)0 ) '代わりに – UnholySheep

+0

情報をありがとう。それは理にかなっている。私はすぐに他の場所からそれをコピーしました。私はそれを修正するために編集します。 – user2445507

答えて

0

マクロは依然として便利です "条件付きコンパイル" - 少なくともほとんどのコンパイラの呼び出しの引数でそれらを定義または定義解除できるという利点があります。

例えば、これは、#include <cassert>assertにおいて有用であり、NDEBUGマクロとの関係。


SPEAK_ENABLEDがタイプまたは非タイプのいくつかのコンパイル時の特性に依存した場合は、テンプレートを使用することができ、あなたはどうするつもりですかそれはあなたのユースケースに依存します。

ただし、SPEAK_ENABLEDがコンパイラの呼び出し前にわかっていたいくつかの環境プロパティに依存する場合、MACROはまだまだ関連性があります。


これは、上記のような単純な例のために動作しますが、彼らは、彼らがリンクされているとき 関数の定義を欠いて文句を言うだろうので、それは私の ライブラリでは動作しません。

speak()の空の定義を「無効化のケース」に指定すると、適切なオプティマイザがコールを削除する可能性があります。

+0

テンプレートに関する私の問題は、依存関係の問題です。たとえば、intをテンプレートパラメータとして受け入れる関数を定義することはできますが、私のmain.cppファイルからそのintを定義してライブラリに取り込むことはできません。この場合、唯一の解決策はマクロだと思います。 – user2445507

+0

これはマクロでコンパイルされましたが、同様の問題があります。マクロは依存ライブラリには設定されていないので、main.cpp実行可能ファイルは無効になっていますが、speak()関数全体を実行します。私は本当にそれを私の従属ライブラリすべてで動作させるために、もっと複雑なmakefileを使う必要があるかもしれません... – user2445507

関連する問題