22

withPascal のキーワードを使用して、レコードのフィールドにすばやくアクセスできます。C++ に似たようなものがあるかどうかは誰にもわかりませんか?

例: 多くのフィールドを持つポインターがあり、次のように入力したくありません。

if (pointer->field1) && (pointer->field2) && ... (pointer->fieldn)

私が本当に欲しいのは、C++で次のようなものです:

with (pointer)
{
  if (field1) && (field2) && .......(fieldn)
}
4

19 に答える 19

24

おそらくあなたが得ることができる最も近いものはこれです:(私に反対票を投じないでください;これは単なる学術的な演習です。もちろん、これらの人工withブロックの本体でローカル変数を使用することはできません!)

struct Bar {
    int field;
};

void foo( Bar &b ) {
    struct withbar : Bar { void operator()() {
        cerr << field << endl;
    }}; static_cast<withbar&>(b)();
}

または、もう少し悪魔的に、

#define WITH(T) do { struct WITH : T { void operator()() {
#define ENDWITH(X) }}; static_cast<WITH&>((X))(); } while(0)

struct Bar {
    int field;
};

void foo( Bar &b ) {
    if ( 1+1 == 2 )
        WITH( Bar )
            cerr << field << endl;
        ENDWITH( b );
}

またはC++0xで

#define WITH(X) do { auto P = &X; \
 struct WITH : typename decay< decltype(X) >::type { void operator()() {
#define ENDWITH }}; static_cast<WITH&>((*P))(); } while(0)

        WITH( b )
            cerr << field << endl;
        ENDWITH;
于 2010-02-17T08:38:19.517 に答える
19

いいえ、そのようなキーワードはありません。

于 2010-02-17T08:21:38.280 に答える
14

私は使用するのが好きです:

    #define BEGIN_WITH(x) { \
        auto &_ = x;

    #define END_WITH() }

例:

    BEGIN_WITH(MyStructABC)
    _.a = 1;
    _.b = 2;
    _.c = 3;
    END_WITH()
于 2015-02-21T11:37:12.127 に答える
10

C++ では、 によって参照されるクラスのメソッドにコードを入れることができますpointer。そこでは、ポインターを使用せずにメンバーを直接参照できます。それを作るとinline、あなたが望むものをほとんど手に入れることができます。

于 2010-02-17T08:25:33.500 に答える
9

私は主にwithキーワードを持つ Delphi でプログラミングしていますが (Delphi は Pascal の派生物であるため) with、. 他の人が言ったように、タイピングは少し節約できますが、読むのは難しくなります.

以下のコードのような場合、使用したくなるかもしれませんwith:

cxGrid.DBTableView.ViewData.Records.FieldByName('foo').Value = 1;
cxGrid.DBTableView.ViewData.Records.FieldByName('bar').Value = 2;
cxGrid.DBTableView.ViewData.Records.FieldByName('baz').Value = 3;

これを使うwithとこんな感じ

with cxGrid.DBTableView.ViewData.Records do
begin
  FieldByName('foo').Value = 1;
  FieldByName('bar').Value = 2;
  FieldByName('baz').Value = 3;
end;

同じものを指す追加の変数を導入することにより、別の手法を使用することを好みますwith。このような:

var lRecords: TDataSet;

lRecords := cxGrid.DBTableView.ViewData.Records;

lRecords.FieldByName('foo').Value = 1;
lRecords.FieldByName('bar').Value = 2;
lRecords.FieldByName('baz').Value = 3;

このようにしてあいまいさはありません。タイピングを少し節約でき、コードの意図は使用するよりも明確です。with

于 2010-02-17T09:02:16.910 に答える
5

C++ にはそのような機能はありません。また、多くの人が Pascal の "WITH" を問題と考えています。これは、コードがあいまいになり、読みにくくなる可能性があるためです。Pascal では、"With Var1,Var2" などの複数の with-variables も許可されているため、さらに難しくなっています。

于 2010-02-17T08:25:48.607 に答える
5

いいえ、C++ にはそのようなキーワードはありません。

于 2010-02-17T08:22:06.053 に答える
4

あなたが得ることができる最も近いものはメソッドチェーンです:

myObj->setX(x)
     ->setY(y)
     ->setZ(z)

複数のフィールドの設定とusing名前空間の場合。

于 2010-02-17T12:34:50.147 に答える
3
with (OBJECT) {CODE}

C++ にはそのようなものはありません。
CODE をそのまま OBJECT のメソッドに入れることができますが、常に望ましいとは限りません。

C++11 では、OBJECT の短い名前でエイリアスを作成することで、かなり近づけることができます。
たとえば、問題のコードは次のようになります。

{
    auto &_ = *pointer;
    if (_.field1 && ... && _.fieldn) {...}
}

(周囲の中括弧は、エイリアスの可視性を制限するために使用されます_)

フィールドを頻繁に使用する場合は、直接エイリアスを作成できます。

auto &field = pointer->field;
// Even shorter alias:
auto &_ = pointer->busy_field;
于 2014-12-27T20:59:31.007 に答える
1

次のアプローチはBoostに依存しています。コンパイラがC++0xをサポートしている場合autoは、それを使用してBoost依存関係を取り除くことができます。

免責事項:他の誰かが(または数か月以内に自分で)維持または読み取る必要のあるコードでは、これを行わないでください。

#define WITH(src_var)                                             \
    if(int cnt_ = 1)                                              \
        for(BOOST_AUTO(const & _, src_var); cnt_; --cnt_)


int main()
{
    std::string str = "foo";

    // Multiple statement block
    WITH(str)
    {
        int i = _.length();
        std::cout << i << "\n";
    }

    // Single statement block
    WITH(str)
        std::cout << _ << "\n";

    // Nesting
    WITH(str)
    {
        std::string another("bar");
        WITH(another)
            assert(_ == "bar");
    }
}
于 2010-02-17T11:19:13.603 に答える
1

数多くのパーサーを書いてきたので、これは名前付きオブジェクト (静的または動的) を検索する非常に単純なリストのように見えます。さらに、コンパイラが欠落しているオブジェクトと型を正しく識別しなかった状況を見たことがありません。そのため、WITH ...ENDWITH 構造を許可しないという言い訳はすべて、ばかげているように思えます。長いオブジェクト名を使いがちな私たちにとって、回避策の 1 つは単純な定義を作成することです。私が持っていると仮定して、抵抗できませんでした:

    #include<something> 
    typedef int headache;
    class grits{
      public:
       void corn(void);
       void cattle(void);
       void hay(void);}; //insert function defs here
     void grits::grits(void)(printf("Welcome to Farm-o-mania 2012\n");};

    #define m mylittlepiggy_from_under_the_backporch.
    headache main(){
       grits mylittlepiggy_from_under_the_backporch;
         m corn();  //works in GCC
         m cattle();
         m hay();
      return headache;
于 2012-09-30T05:57:51.330 に答える
0

たぶんあなたはできる:

auto p = *pointer;
if (p.field1) && (p.field2) && ... (p.fieldn)

withまたは、C ++のステートメントを理解し、それらを何らかの形式の有効なC++に変換する小さなプログラムを作成します。

于 2011-10-20T19:05:16.037 に答える
0

「with」が実際に役立つ例が 1 つあります。

再帰的なデータ構造のメソッドでは、次のようなケースがよくあります。

void A::method()
{
  for (A* node = this; node; node = node->next) {
    abc(node->value1);
    def(value2); // -- oops should have been node->value2
    xyz(node->value3);
  }
}

このようなタイプミスによるエラーは、見つけるのが非常に困難です。

「with」を使用すると、次のように書くことができます

void A::method()
{
  for (A* node = this; node; node = node->next) with (node) {
    abc(value1);
    def(value2);
    xyz(value3);
  }
}

これはおそらく、「with」について言及されている他のすべてのネガを上回っているわけではありませんが、興味深い情報として...

于 2010-07-17T11:05:39.017 に答える