O C++ tem "com a" palavra-chave como Pascal?
-
21-09-2019 - |
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)
}
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.