39

#include 本体にディレクティブを含むマクロを定義する方法はありますか?

「」を入れるだけ#includeでエラーになります

C2162: "expected macro formal parameter"

ここでは、#文字列を連結するために使用していません。
「」を使用すると\# include、次の2つのエラーが発生します。

error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion

何か助けはありますか?

4

9 に答える 9

27

他の人が言うように、いいえ、マクロ内に #include ステートメントを含めることはできません。プリプロセッサは 1 つのパスしか実行しないためです。ただし、最近使用していることに気付いた危険なトリックを使用して、プリプロセッサに基本的に同じことをさせることができます。

プリプロセッサ ディレクティブは、マクロ内では何も実行しませんが、ファイル内では実行することに注意してください。したがって、変更したいコードのブロックをファイルに貼り付け、それをマクロ定義のように考えて (他のマクロによって変更できる部分を含む)、この疑似マクロ ファイルをさまざまな場所に #include することができます (makeインクルードガードがないことを確認してください!)。#include は基本的にあるファイルの内容を別のファイルにダンプするだけなので、マクロとまったく同じようには動作しませんが、かなりマクロに似た結果を得ることができます。

たとえば、グループに含まれる類似した名前のヘッダーを多数含めることを検討してください。それらをすべて書き出すのは面倒ですし、自動生成されることさえあります。次のようなことを行うことで、それらの組み込みを部分的に自動化できます。

ヘルパー マクロ ヘッダー:

/* tools.hpp */

#ifndef __TOOLS_HPP__
#def __TOOLS_HPP__

// Macro for adding quotes
#define STRINGIFY(X) STRINGIFY2(X)    
#define STRINGIFY2(X) #X

// Macros for concatenating tokens
#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_2 CAT
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))
#define CAT_4(A,X,Y,Z) CAT(A,CAT_3(X,Y,Z))
// etc...

#endif

疑似マクロファイル

/* pseudomacro.hpp */

#include "tools.hpp"
// NO INCLUDE GUARD ON PURPOSE
// Note especially FOO, which we can #define before #include-ing this file,
// in order to alter which files it will in turn #include.
// FOO fulfils the role of "parameter" in this pseudo-macro.

#define INCLUDE_FILE(HEAD,TAIL) STRINGIFY( CAT_3(HEAD,FOO,TAIL) )

#include INCLUDE_FILE(head1,tail1.hpp) // expands to #head1FOOtail1.hpp
#include INCLUDE_FILE(head2,tail2.hpp)
#include INCLUDE_FILE(head3,tail3.hpp)
#include INCLUDE_FILE(head4,tail4.hpp)
// etc..

#undef INCLUDE_FILE

ソースファイル

/* mainfile.cpp */

// Here we automate the including of groups of similarly named files

#define FOO _groupA_
#include "pseudomacro.hpp"
// "expands" to: 
// #include "head1_groupA_tail1.hpp"
// #include "head2_groupA_tail2.hpp"
// #include "head3_groupA_tail3.hpp"
// #include "head4_groupA_tail4.hpp"
#undef FOO

#define FOO _groupB_
#include "pseudomacro.hpp"
// "expands" to: 
// #include "head1_groupB_tail1.hpp"
// #include "head2_groupB_tail2.hpp"
// #include "head3_groupB_tail3.hpp"
// #include "head4_groupB_tail4.hpp"
#undef FOO

#define FOO _groupC_
#include "pseudomacro.hpp"
#undef FOO

// etc.

これらのインクルードは、Bing Jian の要求による回答として、繰り返したいコード ブロックの途中にある可能性もあります (FOO が変更されています): #include ディレクティブを含むマクロ定義

私はこのトリックを広範囲に使用したことはありませんが、これで私の仕事は完了です。明らかに、必要な数の「パラメーター」を持つように拡張でき、そこで好きなプリプロセッサー コマンドを実行して、実際のコードを生成できます。マクロ内にインクルードを貼り付けることができないため、通常のマクロのように、作成したものを別のマクロへの入力として使用することはできません。しかし、それは別の疑似マクロの中に入ることができます:)。

他の人は、他の制限、および何がうまくいかないかについてコメントするかもしれません:)。

于 2015-01-07T23:04:15.497 に答える
18

そのメリットについては議論しませんが、freetype(www.freetype.org)は次のことを行います。

#include FT_FREETYPE_H

他の場所でFT_FREETYPE_Hを定義する場所

于 2008-11-05T21:10:05.680 に答える
7

C および C++ 言語では、マクロ展開の結果としてプリプロセッサ ディレクティブを形成することを明示的に禁止しています。つまり、プリプロセッサ ディレクティブをマクロ置換リストに含めることはできません。また、連結によって新しいプリプロセッサ ディレクティブを "構築" してプリプロセッサをだまそうとすると (およびそのようなトリック)、動作は未定義です。

于 2010-08-31T21:23:33.887 に答える
6

C/C++ プリプロセッサはコードを 1 回しかパスしないと思うので、うまくいかないと思います。マクロによってコードに「#include」を配置できる場合がありますが、コンパイラはそれをどう処理すればよいかわからないため、それを詰まらせてしまいます。あなたがやろうとしていることは、 #include を取得するために、プリプロセッサがファイルに対して 2 番目のパスを実行する必要があることです。

于 2008-11-05T20:30:43.500 に答える
4

私もこれをやりたかったのですが、理由は次のとおりです。

C または C++ でコンパイルしている場合、一部のヘッダー ファイル (特に OpenMPI の mpi.h) は異なる動作をします。C++ プログラムから C MPI コードにリンクしています。ヘッダーを含めるために、私はいつものようにします:

extern "C" {
#include "blah.h"
}

__cplusplusしかし、C リンケージでも が定義されているため、これは機能しません。つまり、blah.h に含まれる mpi.h がテンプレートの定義を開始し、C リンケージでテンプレートを使用できないと言ってコンパイラが終了します。

したがって、blah.h で行う必要があるのは、置き換えることです。

#include <mpi.h>

#ifdef __cplusplus
#undef __cplusplus
#include <mpi.h>
#define __cplusplus
#else
#include <mpi.h>
#endif

驚くべきことに、この病的なことを行うのは mpi.h だけではありません。したがって、指定されたファイルに対して上記を実行するマクロを定義したいと思いINCLUDE_AS_Cます。しかし、それはうまくいかないと思います。

誰かがこれを達成する別の方法を理解できる場合は、私に知らせてください。

于 2010-08-31T21:16:16.107 に答える
3

私もから得たように、このタスクは不可能に思えますが、あなたは大丈夫だと思います

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#

いいえ、C++ (および C) のプリプロセッサ ディレクティブは反映されません。

パヴェル・ジェパック

とにかく、この試みの背後にある理由は、次の繰り返し使用されるコード スニペットをマクロとして作成しようとしているからです。

void foo(AbstractClass object)
{
    switch (object.data_type())
    {
    case AbstractClass::TYPE_UCHAR :
        {
        typedef unsigned char PixelType;
        #include "snippets/foo.cpp"
        }
        break;
    case AbstractClass::TYPE_UINT:
        {
        typedef unsigned int PixelType;
        #include "snippets/foo.cpp"
        }
        break;
    default:
        break;
    }
}

別のタスクについては、同様の機能が必要です

void bar(AbstractClass object)

どこに置くか

#include "snippets/bar.cpp"

もちろん、タスク固有のコードが記述されているのは「snippets/foo.cpp」と「snippets/bar.cpp」です。

于 2008-11-05T21:00:17.450 に答える
0

あなたが実際に何をしようとしているのかわかりませんが、あなたが望むのはテンプレート化された関数のようです。

このように、PixelTypeはコードブロックの単なるテンプレートパラメータです。

于 2008-11-05T21:16:59.257 に答える
0

マクロに#includeが必要なのはなぜですか?マクロが含まれているファイルを#includeする場合は、マクロの上に#includeを配置し、残りのすべての#includeステートメントを含めることができます。すべてが素晴らしくてダンディなはずです。

ファイルに含めることができないものをマクロに含める理由はありません。

于 2008-11-05T20:29:32.423 に答える
-8

伝染性は正しいです-あなたがしているなら:

myFile.c:

#include "standardAppDefs.h"
#myStandardIncludeMacro

standardAppDefs.h:

#define myStandardIncludeMacro #include <foo.h>

なぜ言わないのですか:

myFile.c:

#include "standardAppDefs.h"

standardAppDefs.h:

#include <foo.h>

マクロをお忘れですか?

于 2008-11-05T20:41:49.217 に答える