views:

510

answers:

10

with keyword in Pascal can be use to quick access the field of a record. Anybody knows if C++ has anything similar to that?

Ex: I have a pointer with many fields and i don't want to type like this:

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

what I really want is something like this in C++:

with (pointer)
{
  if (field1) && (field2) && .......(fieldn)
}
+6  A: 

no there is no such keyword.

rerun
+5  A: 

No, C++ does not have any such keyword.

dirkgently
+8  A: 

In C++, you can put code in a method of the class being reference by pointer. There you can directly reference the members without using the pointer. Make it inline and you pretty much get what you want.

What do you mean for “make it `inline`”? Can you declare the method just inside another function? It's weird...
Dacav
+3  A: 

C++ does not have a feature like that. And many consider "WITH" in Pascal to be a problem because it can make the code ambiguous and hard to read, for example it hard to know if field1 is a member of pointer or a local variable or something else. Pascal also allows multiple with-variables such as "With Var1,Var2" which makes it even harder.

Ville Krumlinde
There is always the question that if something can be abused, means that it is bad.
Marco van de Voort
Sure, because name lookup in C++ is *so straightforward*. No -1, but I think the "can make code ambiguous" argument falls flat when you consider the case of argument-dependent lookup for functions, especially for instantiations of function templates.
j_random_hacker
I agree it can be useful but I've seen it abused so many times now that I stay away from using it. In particular it can bite you if field1 is renamed in the record so your with-code now suddenly silently refers to another variable in scope with the same name. Instead of with I use one of the other approaches suggested here: use a local variable with short name or move it to a function/method.
Ville Krumlinde
Upvote. The worst language feature. Consider this abomination: with struct1, struct2.substruct3, struct4.substruct5.ptrstruct6^... Seen it.
Nikola Gedelovski
Visual Basic tidied up the syntax by requiring the fields belonging to the 'with' to be prefixed with a "." - it also helped syntax completion etc. Our host Joel did that :)
Will
+6  A: 

Probably the closest you can get is this: (Please don't downvote me; this is just an academic exercise. Of course, you can't use any local variables in the body of these artificial with blocks!)

struct Bar {
    int field;
};

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

Or, a bit more demonically,

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

or 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;
Potatoswatter
Interesting approach! :)
j_random_hacker
Very nice :). I'd like to mention though that for those few of us that work with the Metrowerks compiler, this is quite likely not to work (it doesn't deal well with structs in a function)
arke
@arke: really? That's surprising, I loved Metrowerks when it was the Mac standard. Hmm, it looks like they lost Howard Hinnant…
Potatoswatter
you can use static variables though.
Alexandre C.
+3  A: 

Even though I program mostly in Delphi which has a with keyword (since Delphi is a Pascal derivative), I don't use with. As others have said: it saves a bit on typing, but reading is made harder.

In a case like the code below it might be tempting to use 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;

Using with this looks like this

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

I prefer to use a different technique by introducing an extra variable pointing to the same thing with would be pointing to. Like this:

var lRecords: TDataSet;

lRecords := cxGrid.DBTableView.ViewData.Records;

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

This way there is no ambiguity, you save a bit on typing and the intent of the code is clearer than using with

Otherside
j_random_hacker
A: 

The following approach relies on Boost. If your compiler supports C++0x's auto then you can use that and get rid of the Boost dependence.

Disclaimer: please don't do this in any code that must be maintained or read by someone else (or even by yourself in a few months):

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

First I've heard that anybody doesn't like 'with'. The rules are perfectly straightforward, no different from what happens inside a class in C++ or Java. And don't overlook that it can trigger a significant compiler optimization.

EJP
+2  A: 

The closest you can get is method chaining:

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

for setting multiple fields and using for namespaces.

aib
A: 

I can see one instance where 'with' is actually useful.

In methods for recursive data structures, you often have the case:

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

errors caused by typos like this are very hard to find.

With 'with' you could write

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

This probably doesn't outweight all the other negatives mentioned for 'with', but just as an interesting info...

Jay