Domanda

with parola chiave in Pascal può essere utilizzato per un rapido accesso al campo di un record. Qualcuno sa se C ++ ha qualcosa di simile a questo?

Ex: Ho un puntatore con molti campi e io non voglio scrivere in questo modo:

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

quello che voglio veramente è qualcosa di simile in C ++:

with (pointer)
{
  if (field1) && (field2) && .......(fieldn)
}
È stato utile?

Soluzione

In C ++, è possibile inserire il codice in un metodo di riferimento di classe essere da pointer. C'è possibile fare riferimento direttamente i membri senza utilizzare il puntatore. Ne fanno inline ed è praticamente ottenere quello che vuoi.

Altri suggerimenti

Probabilmente il più vicino si può ottenere è questo: (Per favore non mi downvote, questo è solo un esercizio accademico Naturalmente, non è possibile utilizzare tutte le variabili locali nel corpo di questi blocchi with artificiali.!)

struct Bar {
    int field;
};

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

In alternativa, un po 'più demoniaco,

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

non v'è alcuna parola chiave.

Mi piace usare:

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

    #define END_WITH() }

Esempio:

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

Anche se programmo per lo più in Delphi che ha una parola chiave with (dal momento che Delphi è un derivato Pascal), io non uso with. Come altri hanno detto:. Fa risparmiare un po 'di battitura, ma la lettura è reso più difficile

In un caso come il codice qui sotto si potrebbe essere tentati di utilizzare 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;

Utilizzando with questo assomiglia a questo

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

Io preferisco usare una tecnica diversa con l'introduzione di una variabile che punta in più per la stessa with cosa sarebbe indicando a. In questo modo:

var lRecords: TDataSet;

lRecords := cxGrid.DBTableView.ViewData.Records;

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

In questo modo non c'è ambiguità, si risparmia un po 'di battitura e l'intento del codice è più chiaro che usando with

No, C ++ non ha un tale parola chiave.

C ++ non ha una funzione simile. E molti considerano "CON" in Pascal ad essere un problema perché può rendere il codice ambiguo e difficile da leggere, ad esempio, è difficile sapere se campo1 è un membro del puntatore o una variabile locale o qualcos'altro. Pascal permette anche di più con-variabili come "Con Var1, Var2", che rende ancora più difficile.

Il più vicino si può ottenere è metodo concatenamento :

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

per l'impostazione più campi e using per i namespace.

with (OBJECT) {CODE}

Non esiste una cosa come in C ++.
È possibile inserire il codice come è in un metodo di oggetto, ma non è sempre auspicabile.

Con C ++ 11 è possibile ottenere abbastanza vicino con la creazione di alias con nome breve per oggetto.
Ad esempio di codice dato in questione apparirà in questo modo:

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

(Le parentesi graffe circostanti sono utilizzati per limitare la visibilità di alias _)

Se si usa un po 'di campo molto spesso è possibile alias direttamente:

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

In primo luogo ho sentito che qualcuno non piace 'con'. Le regole sono perfettamente semplice, non è diverso da ciò che accade all'interno di una classe in C ++ o Java. E non dimenticare che è possibile attivare una significativa ottimizzazione del compilatore.

Dopo aver scritto numerosi parser, questa sembra una lista morto semplice sguardo per l'oggetto di nome, statici o dinamici. Inoltre, non ho mai visto una situazione in cui il compilatore non ha identificato correttamente l'oggetto e il tipo mancante, quindi tutte quelle scuse per non consentire a con ... costruzione ENDWITH sembrerebbe essere un sacco di sciocchezze. Per il resto di noi inclini a nomi lungo oggetto soluzione è creare definisce semplici. non ha potuto resistere, supponiamo di avere:

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

Il seguente approccio si basa su Boost. Se il compilatore supporta auto del C ++ 0x, allora è possibile utilizzare tale e sbarazzarsi della dipendenza Boost.

responsabilità : si prega di non farlo in qualsiasi codice che deve essere mantenuto o letto da qualcun altro (o anche da soli in pochi mesi):

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

Posso vedere un caso in cui 'con' è effettivamente utile.

Nel metodi per strutture di dati ricorsive, si ha spesso il 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);
  }
}

errori causati da errori di battitura come questo sono molto difficili da trovare.

Con 'con' si potrebbe scrivere

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

Questo probabilmente non siano superiori tutti gli altri aspetti negativi menzionati per 'con', ma altrettanto un info interessante ...

Forse è possibile:

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

O creare un piccolo programma che capirà le dichiarazioni with in C ++ e tradurli ad una qualche forma di una valida C ++.

No, non v'è alcuna parola chiave with in C / C ++.

Ma è possibile aggiungere con un po 'di codice preprocessore:

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

Utilizzo:

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

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

semplificati definizioni unoverloaded (sceglierne una):

senza nome (Kotlin stile it):

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

denominato:

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

Naturalmente il ciclo for ha sempre una sola passata e verrà ottimizzato dal compilatore.

#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 ha detto ...

Un modo semplice per farlo è la seguente

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

Ho scritto python tutto il giorno e appena demolito questo giù prima che qualcuno mi prende per la pulizia. In un programma più ampio questo è un esempio di come mantenere un conteggio affidabile per qualcosa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top