0

私は適切な#define関数のようなマクロを書こうとして頭を悩ませてきましたが、動けなくなりました。これが私が取り組んでいる例です:

#include <iostream>
#define pMAKE(x,y,z,dest)\
    (dest).(x) = (x);\
    (dest).(y) = (y);\
    (dest).(z) = (z);

struct pt {
    double x, y, z;
};

int main() {
    pt p;
    pMAKE(0,1,2,p);
    return 0;
}

そして、私が得ているエラー:

A.cpp: In function ‘int main()’:
A.cpp:13: error: expected unqualified-id before ‘(’ token
A.cpp:13: error: expected unqualified-id before ‘(’ token
A.cpp:13: error: expected unqualified-id before ‘(’ token

エラーは何を意味し、エラーが発生するのはなぜですか? 以下を思い通りに動作させることができましたが、正直なところ運が良かったので、何が起こっているのか真剣に理解していません.

#define pMAKE(X,Y,Z,dest)\
    dest.x = (X);\
    dest.y = (Y);\
    dest.z = (Z);

私はあらゆる助けに感謝します!

4

6 に答える 6

7

マクロの最初のバージョンでは、次のようにpMAKE(0,1,2,p);展開されます

p.0 = 0;
p.1 = 1;
p.2 = 2;;

つまり、変数名 (割り当ての左側) とプリプロセッサによって置き換えられるラベル (割り当ての右側) の両方として, ,を使用して、 x, y, のzメンバーへの参照を前処理しました。割り当て)。ptxyz

(Konrad Rudolph が指摘したように) 残念ながら、マクロにはまだ別の重大なエラーがあります。フォームのコードを検討してください

pt p;
if (foo)
    pMAKE(0,1,2,p);

に展開します

pt p;
if (foo)
    p.x = 0;
p.y = 1;  // happens regardless of 'foo' test
p.z = 2;; // happens regardless of 'foo' test

マクロを

#define pMAKE(X,Y,Z,dest)\
    do { \
        (dest).x = (X);\
        (dest).y = (Y);\
        (dest).z = (Z);\
    } while (0)
于 2013-02-07T15:26:32.873 に答える
6
struct pt {
    double x, y, z;
    pt(double _x, double _y, double _z) : x(_x), y(_y), z(_z) { }
};

pt p (0.0, 1.0, 2.0);

C++ でマクロを使用しないでください。

または、@potatoswatter が提案したように、C++11ですぐに完了させます

struct pt { double x, y, z; };
pt p = { 0.0, 1.0, 2.0 };
于 2013-02-07T15:26:26.230 に答える
3

エラーの意味と、なぜエラーが発生するのですか?

マクロは、そのパラメーターのすべての出現箇所を引数に置き換えます。それで

(dest).(x) = (x)

になります

(dest).(0) = (0)

これはナンセンスです。コンパイラーはメンバー名(言語構文では「unqualified-id」と呼ばれる識別子)を予期しますが、(0)代わりにそれを認識します。

2番目のバージョンでは、xはパラメーター名でdest.xはないため、変更されません。

より良いアプローチは、マクロを避けることです。関数を使用します:

pt make_pt(double x, double y, double z) {
    pt p;
    p.x = x; 
    p.y = y;
    p.z = z;
    return p;
}

int main() {
    pt p = make_pt(0,1,2);
}

または、集約初期化を使用します。

int main() {
    pt p = {0,1,2};
}

また、C ++ 11では、初期化子リストからの割り当て:

p = {4,5,6};
于 2013-02-07T15:29:49.983 に答える
2

マクロはテキストの置換として機能します。マクロのパラメータが置換リストに表示される場所はどこでも、引数にテキストで置き換えられます。したがって、あなたの場合、次のようにpMAKE(0, 1, 2, p);展開されます。

(p).(0) = (0);
(p).(1) = (1);
(p).(2) = (2);;

(実際には、マクロは改行を保持しないため、すべて 1 行になりますが、わかりやすくするために 3 行にします)。

あなたの場合、マクロは必要ありません。インライン関数 (おそらく のメンバー関数またはコンストラクターpt) が必要です。テキストの性質が必要な場合にのみマクロを使用してください (トークンを識別子に結合するなど)。それ以外の場合は、(インライン) 関数を使用します。このような:

struct pt
{
  double x, y, z;
  pt(double ax, double ay, double az) : x(ax), y(ay), z(az) {}
};

int main()
{
  pt p(0, 1, 2);
}
于 2013-02-07T15:31:49.713 に答える
2

インライン関数を使用し、

pt& pMake(int x, int y, int z, pt&p){
    p.x=x;
    p.y=y;
    p.z=z;
    return p;
};
于 2013-02-07T15:32:51.380 に答える
1

メンバーアクセスは、.(x)誤ってパラメーターの名前を使用しますx。(また、メンバーアクセスの第2オペランドは式ではないため、括弧は属しません。)ベストプラクティスは、名前の衝突を防ぐために、すべてのマクロ名とマクロパラメーターをすべて大文字で保持することです。また、単一文字の識別子も避けてください。

#define POINT_MAKE(X,Y,Z,DEST)\
    (DEST).x = (X);\
    (DEST).y = (Y);\
    (DEST).z = (Z);
于 2013-02-07T15:29:27.487 に答える