Есть ли в 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 ]

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

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

0 голосов
/ 10 июня 2019

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

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 весь день и просто записал это, прежде чем кто-нибудь отвезет меня к уборщицам. В более крупной программе это пример того, как вести надежный подсчет чего-либо.

0 голосов
/ 06 марта 2019
#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;
}

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

0 голосов
/ 26 августа 2018

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

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

/* 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 всегда имеет только один проход и будет оптимизирован компилятором.

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

Следующий подход основан на 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");
    }
}
0 голосов
/ 20 октября 2011

Может быть, вы можете:

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

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

0 голосов
/ 17 июля 2010

Я вижу один случай, когда 'with' действительно полезен.

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

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

Ошибки, вызванные такими опечатками, очень трудно найти.

С помощью 'с' вы можете написать

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...