Подтвердить что ты не робот

Имеет ли С++ "с" ключевое слово, такое как Pascal?

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

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

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

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

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

Ответ 1

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

Ответ 2

Вероятно, самое близкое, что вы можете получить, это следующее: (Пожалуйста, не уменьшайте меня, это просто академическое упражнение. Конечно, вы не можете использовать какие-либо локальные переменные в теле этих искусственных блоков 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 );
}

или в С++ 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;

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

    #define END_WITH() }

Пример:

    BEGIN_WITH(MyStructABC)
    _.a = 1;
    _.b = 2;
    _.c = 3;
    END_WITH()

Ответ 6

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

Ответ 7

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

Ответ 8

Ближе всего вы можете получить цепочка методов:

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

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

Ответ 9

Сначала я слышал, что кому-то не нравится "с". Правила совершенно просты, ничем не отличаются от того, что происходит внутри класса на С++ или Java. И не забывайте, что это может вызвать значительную оптимизацию компилятора.

Ответ 10

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

    #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;

Ответ 11

with (OBJECT) {CODE}

В С++ такой вещи нет.
Вы можете поместить CODE как есть в метод OBJECT, но это не всегда желательно.

С С++ 11 вы можете приблизиться, создав псевдоним с коротким именем для OBJECT.
Например, данный код будет выглядеть так:

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

(Окружающие фигурные скобки используются для ограничения видимости псевдонима _)

Если вы используете какое-то поле очень часто, вы можете его напрямую перенести:

auto &field = pointer->field;
// Even shorter alias:
auto &_ = pointer->busy_field;

Ответ 12

Следующий подход основан на Boost. Если ваш компилятор поддерживает С++ 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");
    }
}

Ответ 13

Я вижу один экземпляр, где "с" действительно полезно.

В методах рекурсивных структур данных вы часто имеете дело:

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);
  }
}

Это, вероятно, не лишний вес всех других негативов, упомянутых для "с", но просто как интересная информация...

Ответ 14

Возможно, вы можете:

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

Или создайте небольшую программу, которая будет понимать инструкции with в С++ и перевести их в какую-либо форму допустимого С++.

Ответ 15

Нет, with ключевым словом в C/C++ нет.

Но вы можете добавить его с помощью некоторого кода препроцессора:

/* Copyright (C) 2018 Piotr Henryk Dabrowski, Creative Commons CC-BY 3.0 */

#define __M2(zero, a1, a2, macro, ...) macro

#define __with2(object, as) \
    for (typeof(object) &as = (object), *__i = 0; __i < (void*)1; ++__i)

#define __with1(object) __with2(object, it)

#define with(...) \
    __M2(0, ##__VA_ARGS__, __with2(__VA_ARGS__), __with1(__VA_ARGS__))

Использование:

with (someVeryLongObjectNameOrGetterResultOrWhatever) {
    if (it)
        it->...
    ...
}

with (someVeryLongObjectNameOrGetterResultOrWhatever, myObject) {
    if (myObject)
        myObject->...
    ...
}

Упрощенные незагруженные определения (выберите одно):

безымянный (Котлин стиль it):

#define with(object) \
    for (typeof(object) &it = (object), *__i = 0; __i < (void*)1; ++__i)

по имени:

#define with(object, as) \
    for (typeof(object) &as = (object), *__i = 0; __i < (void*)1; ++__i)

Конечно, цикл for всегда имеет только один проход и будет оптимизирован компилятором.

Ответ 16

#include <iostream>

using namespace std;

template <typename T>
struct with_iter {
  with_iter( T &val ) : p(&val) {}

  inline T* begin() { return p; }
  inline T* end() { return p+1; }

  T *p;
};

#define with( N, I ) for( auto &N : with_iter<decltype(I)>(I) )

int main() {

  with( out , cout ) {
    out << "Hello world!" << endl;
  }

  return 0;
}

Нуф сказал...

Ответ 17

Простой способ сделать это заключается в следующем

class MyClass
{
    int& m_x;

    public MyClass(int& x)
    {
        m_x = x;
        m_x++;
    }

    ~MyClass()
    {
        m_x--;
    }
}
int main():
{
    x = 0;
    {
        MyClass(x)  // x == 1 whilst in this scope
    }
}

Я писал Python весь день и просто отменил это, прежде чем кто-нибудь отвезет меня к уборщицам. В более крупной программе это пример того, как вести надежный учет чего-либо.