Pregunta

with La palabra clave en Pascal se puede utilizar para acceder rápidamente al campo de un registro.¿Alguien sabe si C++ tiene algo similar a eso?

Ex:Tengo un puntero con muchos campos y no quiero escribir así:

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

lo que realmente quiero es algo como esto en C++:

with (pointer)
{
  if (field1) && (field2) && .......(fieldn)
}
¿Fue útil?

Solución

En C ++, se puede poner el código en un método de la clase de referencia por ser pointer. Allí se puede hacer referencia directamente a los miembros sin necesidad de utilizar el puntero. Que sea inline y que bastante conseguir lo que quieres.

Otros consejos

Probablemente el más cercano que puede obtener es la siguiente: (Por favor no me Downvote, esto es sólo un ejercicio académico Por supuesto, no se puede utilizar ninguna de las variables locales en el cuerpo de estos bloques with artificiales.!)

struct Bar {
    int field;
};

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

O, un poco más por el demonio,

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

o en 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;

hay no hay tal palabra clave.

Me gusta usar:

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

    #define END_WITH() }

Ejemplo:

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

A pesar de que programo en su mayoría en Delphi, que tiene una palabra clave with (desde Delphi es un derivado de Pascal), yo no uso with. Como han dicho otros:. Ahorra un poco en escribir, pero la lectura se hace más difícil

En un caso como el código de abajo podría ser tentador utilizar 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;

El uso de este with se parece a esto

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

Yo prefiero usar una técnica diferente mediante la introducción de una variable apuntando extra a la misma cosa sería with apuntando. De esta manera:

var lRecords: TDataSet;

lRecords := cxGrid.DBTableView.ViewData.Records;

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

De esta manera no hay ninguna ambigüedad, se ahorra un poco en escribir y la intención del código es más claro que el uso de with

No, C ++ no tiene ninguna tal palabra clave.

C ++ no tiene una característica de esa manera. Y muchos consideran "CON" en Pascal a ser un problema, ya que puede hacer que el código ambiguo y difícil de leer, por ejemplo, que es difícil saber si campo1 es miembro de puntero o una variable local o algo más. Pascal también permite múltiple con variables tales como "Con Var1, var2", que hace que sea aún más difícil.

Lo más cerca que se puede conseguir es método de encadenamiento :

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

para configurar múltiples campos y using de espacios de nombres.

with (OBJECT) {CODE}

No existe tal cosa en C ++.
Puede colocar el código como es en un método de objeto, pero no siempre es deseable.

Con C ++ 11 puede llegar a ser muy estrecha mediante la creación de alias con el nombre abreviado de objeto.
Para el código de ejemplo dado en la pregunta que se verá así:

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

(Las llaves circundantes se utilizan para limitar la visibilidad de _ alias)

Si utiliza algún campo muy a menudo puede crear un alias directamente:

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

En primer lugar he oído a nadie que no le gusta 'con'. Las reglas son perfectamente sencillo, no es diferente de lo que ocurre dentro de una clase en C ++ o Java. Y no pase por alto que puede desencadenar una optimización del compilador significativa.

Después de haber escrito numerosos programas de análisis, esto parece una simple lista muertos mirar hacia arriba para el objeto nombrado, ya sea estática o dinámica. Además, nunca he visto una situación en la que el compilador no identificó correctamente el objeto y el tipo de falta, por lo que todas esas excusas para no permitir que un CON ... construcción ENDWITH parecería ser un montón de tonterías. Para el resto de nosotros propenso a los nombres largos objeto una solución es crear define simples. No se pudo resistir, supongamos que tengo:

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

El siguiente método se basa en Boost. Si su compilador soporta auto de C ++ 0x entonces usted puede utilizar eso y deshacerse de la dependencia Boost.

Aviso Legal : por favor no hacer esto en cualquier código que se debe mantener o leído por otra persona (o incluso por sí mismo dentro de unos meses):

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

Puedo ver un caso en el que 'con' es realmente útil.

En los métodos para estructuras de datos recursivas, a menudo se da el caso:

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

Los errores causados ​​por errores tipográficos como este son muy difíciles de encontrar.

Con 'con' podrías escribir

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

Probablemente esto no supere todos los otros aspectos negativos mencionados para 'con', pero es solo una información interesante...

Tal vez sea posible:

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

O crear un pequeño programa que va a entender los estados with en C ++ y traducirlos a alguna forma de C ++ válida.

No, no hay ninguna palabra clave with en C / C ++.

Sin embargo, se puede añadir que con algo de código preprocesador:

/* 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__))

Uso:

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

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

simplificado definiciones unoverloaded (elija uno):

sin nombre (it estilo Kotlin):

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

llamado:

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

Por supuesto, el bucle for siempre tiene solamente una sola pasada y se optimizará a cabo por el compilador.

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

Nuf dijo ...

Una forma sencilla de hacer esto es como sigue

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

He estado escribiendo todo el día pitón desechó largo y sólo por esta hacia abajo antes de que alguien me lleve a la tintorería. En un programa más amplio que esto es un ejemplo de cómo mantener un recuento fiable para algo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top