问题
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