Does C++ have “with” keyword like Pascal?

元气小坏坏 提交于 2019-12-17 19:32:53

问题


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

回答1:


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.




回答2:


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;



回答3:


no there is no such keyword.




回答4:


I like to use:

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

    #define END_WITH() }

Example:

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



回答5:


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




回答6:


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




回答7:


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.




回答8:


The closest you can get is method chaining:

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

for setting multiple fields and using for namespaces.




回答9:


with (OBJECT) {CODE}

There is no such thing in C++.
You can put CODE as is into a method of OBJECT, but it is not always desirable.

With C++11 you can get quite close by creating alias with short name for OBJECT.
For example code given in question it will look like so:

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

(The surrounding curly braces are used to limit visibility of alias _ )

If you use some field very often you can alias it directly:

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



回答10:


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.




回答11:


Having written numerous parsers, this seems like a dead simple list look up for the named object, either static or dynamic. Further, I have never seen a situation where the compiler did not correctly identify the missing object and type, so all those lame excuses for not allowing a WITH ...ENDWITH construction would seem to be a lot of hooey. For the rest of us prone to long object names one workaround is to create simple defines. Couldn't resist, suppose I have:

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



回答12:


No, there is no with keyword in C/C++.

But you can add it with some preprocessor code:

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

Usage:

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

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

Simplified unoverloaded definitions (choose one):

unnamed (Kotlin style it):

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

named:

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

Of course the for loop always has only a single pass and will be optimized out by the compiler.




回答13:


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



回答14:


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




回答15:


Maybe you can:

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

Or create a small program that will understand with statements in C++ and translate them to some form of a valid C++.




回答16:


#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 said ...




回答17:


A simple way to do this is as follows

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

I've been writing python all day long and just scrapped this down before anyone takes me to the cleaners. In a larger program this is an example of how to keep a reliable count for something.



来源:https://stackoverflow.com/questions/2279180/does-c-have-with-keyword-like-pascal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!