Pergunta

with palavras-chave em Pascal pode ser usado para acesso rápido a campo de um registro.Alguém sabe se o C++ tem nada semelhante a isso?

Ex:Eu tenho um ponteiro com muitos campos, e eu não quero tipo assim:

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

o que eu realmente quero é algo como isso em C++:

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

Solução

Em C ++, você pode colocar código em um método da classe sendo referência por pointer. Lá você pode fazer referência diretamente aos membros sem usar o ponteiro. Faça inline E você tem praticamente o que deseja.

Outras dicas

Provavelmente o mais próximo que você pode obter é o seguinte: (por favor, não me vote; este é apenas um exercício acadêmico. É claro que você não pode usar nenhuma variável local no corpo desses artificiais with Blocks!)

struct Bar {
    int field;
};

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

Ou, um pouco mais demonicamente,

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

ou em 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;

Não, não existe essa palavra -chave.

Eu gosto de usar:

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

    #define END_WITH() }

Exemplo:

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

Mesmo que eu programe principalmente em Delphi, que tem um with Palavra -chave (como Delphi é um derivado Pascal), eu não uso with. Como outros disseram: economiza um pouco na digitação, mas a leitura é mais difícil.

Em um caso como o código abaixo, pode ser tentador usar 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;

Usando with isso se parece com isso

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

Eu prefiro usar uma técnica diferente, introduzindo uma variável extra apontando para a mesma coisa with estaria apontando. Assim:

var lRecords: TDataSet;

lRecords := cxGrid.DBTableView.ViewData.Records;

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

Dessa forma, não há ambiguidade, você economiza um pouco na digitação e a intenção do código é mais clara do que usar with

Não, o C ++ não possui nenhuma palavra -chave.

O C ++ não possui um recurso como esse. E muitos consideram "com" em Pascal como um problema, porque pode tornar o código ambíguo e difícil de ler, por exemplo, é difícil saber se o Field1 é um membro do ponteiro ou uma variável local ou outra coisa. O Pascal também permite múltiplas variáveis, como "com var1, var2", o que torna ainda mais difícil.

O mais próximo que você pode conseguir é encadeamento de método:

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

para definir vários campos e using para namespaces.

with (OBJECT) {CODE}

Não há tal coisa em C++.
Você pode colocar o CÓDIGO como está em um método de OBJETO, mas não é sempre desejável.

Com o C++11, você pode ficar bastante perto de criação de alias com o nome curto para o OBJETO.
Para código de exemplo dado em questão será parecido com isso:

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

(O que cercam as chaves são utilizadas para limitar a visibilidade de alias _ )

Se você usar algum campo, muito frequentemente, você pode alias ele diretamente:

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

Primeiro ouvi dizer que alguém não gosta de 'com'. As regras são perfeitamente diretas, não diferentes do que acontece dentro de uma classe em C ++ ou Java. E não negligencie que pode desencadear uma otimização significativa do compilador.

Tendo escrito inúmeros analisadores, isso parece uma lista simples e morta procurar o objeto nomeado, estático ou dinâmico. Além disso, nunca vi uma situação em que o compilador não identificou corretamente o objeto e o tipo que faltavam; portanto, todas essas desculpas esfarrapadas por não permitirem um ... Endwith Construction parecem ser muito hooey. Para o resto de nós, propensos a nomes de objetos longos, uma solução alternativa é criar define simples. Não pude resistir, suponha que eu tenha:

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

A abordagem a seguir depende do impulso. Se o seu compilador suportar C ++ 0x's auto Então você pode usar isso e se livrar da dependência do impulso.

Isenção de responsabilidade: Por favor, não faça isso em nenhum código que deve ser mantido ou lido por outra pessoa (ou mesmo sozinho em alguns 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");
    }
}

Eu posso ver um exemplo onde 'com' é realmente útil.

Em métodos para recursiva estruturas de dados, muitas vezes, tem o 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);
  }
}

erros causados por erros de digitação como este são muito difíceis de encontrar.

Com o 'com' você poderia escrever

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

Isso provavelmente não outweight todos os outros negativos mencionados para a 'com', mas apenas como uma interessante info...

Talvez você possa:

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

Ou crie um pequeno programa que entenderá with declarações em C ++ e traduzi -las para alguma forma de C ++ válido.

Não, não há with palavra -chave em c/c ++.

Mas você pode adicioná -lo com algum código de pré -processador:

/* 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->...
    ...
}

Definições simplificadas e sem sobrecarregadas (escolha uma):

sem nome (estilo Kotlin it):

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

nomeado:

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

Claro for O loop sempre tem apenas um passe e será otimizado pelo 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 disse ...

Uma maneira simples de fazer isso é a seguinte

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

Escrevo Python o dia inteiro e apenas descartei isso antes que alguém me leve aos produtos de limpeza. Em um programa maior, este é um exemplo de como manter uma contagem confiável para algo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top