Есть ли в C ++ ключевое слово "with", например, Pascal? - PullRequest
16 голосов
/ 17 февраля 2010

with ключевое слово в Паскале можно использовать для быстрого доступа к полю записи. Кто-нибудь знает, есть ли в C ++ что-нибудь подобное?

Ex: У меня есть указатель со многими полями, и я не хочу печатать так:

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

что я действительно хочу, это что-то вроде этого в C ++:

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

Ответы [ 17 ]

20 голосов
/ 17 февраля 2010

Вероятно, самое близкое, что вы можете получить, это: (Пожалуйста, не отрицайте меня; это всего лишь академическое упражнение. Конечно, вы не можете использовать локальные переменные в теле этих искусственных 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;
13 голосов
/ 17 февраля 2010

нет такого ключевого слова нет.

9 голосов
/ 17 февраля 2010

В C ++ вы можете поместить код в метод ссылочного класса с помощью pointer. Там вы можете напрямую ссылаться на членов без использования указателя. Сделайте это inline, и вы в значительной степени получите то, что хотите.

8 голосов
/ 17 февраля 2010

Несмотря на то, что я программирую в основном на Delphi с ключевым словом with (поскольку Delphi является производным от Паскаля), я не использую 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

8 голосов
/ 21 февраля 2015

Мне нравится использовать:

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

    #define END_WITH() }

Пример:

    BEGIN_WITH(MyStructABC)
    _.a = 1;
    _.b = 2;
    _.c = 3;
    END_WITH()
5 голосов
/ 17 февраля 2010

C ++ не имеет такой функции. И многие считают, что «WITH» в Pascal является проблемой, потому что это может сделать код неоднозначным и трудным для чтения, например, трудно понять, является ли field1 членом указателя или локальной переменной или чем-то еще. Паскаль также допускает использование нескольких переменных с переменными типа «С Var1, Var2», что делает его еще сложнее.

4 голосов
/ 17 февраля 2010

Самое близкое, что вы можете получить - метод цепочки :

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

для установки нескольких полей и using для пространств имен.

4 голосов
/ 17 февраля 2010

Нет, в C ++ нет такого ключевого слова.

1 голос
/ 27 декабря 2014
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;
1 голос
/ 30 сентября 2012

Написав множество синтаксических анализаторов, это похоже на мертвый простой список поиска именованного объекта, статического или динамического. Кроме того, я никогда не видел ситуации, когда компилятор неправильно определял отсутствующий объект и тип, поэтому все эти отстойные оправдания за то, что они не допускают конструкцию WITH ... ENDWITH, могут показаться нелепыми. Для остальных из нас, склонных к длинным именам объектов, одним из обходных путей является создание простых определений. Не могу устоять, предположим, у меня есть:

    #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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...