Take for example:
int main(void){
numberComparator comparator1;
comparator1.setA(78.321);
comparator1.showA();
comparator1.setB('c');
comparator1.setB("Yes");
comparator1.setB(124.213);
comparator1.showB();
comparator1.setB(12);
return 0;
}
Instead of saying comparator1 over and over again, can I do something shorter?
I understand that this doesn't really change much about how the program works, but it does make it easier to work around with testing a class I make.
I am doing overloading so that for an assortment of inputs into my comparator, my program can handle them without making the results go crazy. In this case, I want the input to be an int, but what if the input isn't?
The answer could be lying around the internet, but as my title may infer, I do not know how to state the question.
You are looking for something like with keyword which is part of, for example, Pascal language.
Unfortunately, C++ doesn't provide similar feature. Using the references, one can shorten the name of the class and somewhat alleviate the pain, i.e.
Comparator comparator1;
...
{
Comparator& cr = comparator1;
cr.a();
cr.b();
cr.c();
}
It depends. If numberComparator has a "fluent" interface, then each member function will return a reference to *this, and you can write:
comparator1
.setA(78.321)
.showA()
.setB('c')
.setB("Yes")
.setB(124.213)
.showB()
.setB(12);
Note that this is a bitch to debug by step-into (you have to step into every function until you get to the one you are interested in).
The alternative of course is "use a shorter name".
int main(void){
numberComparator c1;
c1.setA(78.321);
c1.showA();
c1.setB('c');
c1.setB("Yes");
c1.setB(124.213);
c1.showB();
c1.setB(12);
return 0;
}
There is really no point in having a particularly long name if it is limited in scope to a few lines. For a local variable, if it isn't limited in scope to a few lines, your function is probably too long.
this is more like an ethical question:
if i have the following code:
void changeInt(int& value)
{
value = 7;
}
and i do:
int number = 3;
changeInt(number);
number will have value 7
I know that when the new stack frame will be created for changeInt function, new variables will be created and &value will point to number.
My concern here is that the caller, if it's not paying attention , can be fooled by thinking that is passing by value which actually, on the function frame , a reference will be created.
I know he can look in the header files and it's a perfect legitimate expression but still I find it unethical a bit :)
i think this should be somehow marked and enforced by syntax. Like in C# where you have ref keyword.
What do you guys think ?
This is one of those things where references are less clear than pointers. However, using pointers may lead to something like this:
changeInt(NULL);
when they actually should have done:
changeInt(&number);
which is just as bad. If the function is as clearly named as this, it's hardly a mystery that it actually changes the value passed in.
Another solution is of course to do:
int calculateNewInt(/* may need some input */)
{
return 7;
}
now
int number = 3;
...
number = calculateNewInt();
is quite obviously (potentially) changing number.
But if the name of the function "sounds like it changes the input value", then it's definitely fair to change the value. If in doubt, read the documentatin. If you write code that has local variables that you don't want to alter, make them const.
const int number = 3;
changeInt(number); /* Makes an error */
(Of course, that means the number is not changeable elsewhere either).
I know he can look in the header files and it's a perfect legitimate expression but still I find it unethical a bit :)
I think that's perfectly normal and part of the language. Actually, this is one of the bad things of C and C++: you have to check the headers all the time when dealing with an unknown API, since when calling a function you don't pass by reference explicitly.
That's not the case for all system languages though. IIRC Rust makes it obligatory to pass references explicitly.
That probably wasn't very clear. Say I have a char *a = "reg". Now, I want to write a function that, on reading the value of a, instantiates an object of a particular class and names it reg.
So for example, say I have a class Register, and a separate function create(char *). I want something like this:
void create(char *s) //s == "reg"
{
//what goes here?
Register reg; // <- this should be the result
}
It should be reusable:
void create(char *s) //s == "second"
{
//what goes here?
Register second; // <- this should be the result
}
I hope I've made myself clear. Essentially, I want to treat the value in a variable as a separate variable name. Is this even possible in C/C++? If not, anything similar? My current solution is to hash the string, and the hash table would store the relevant Register object at that location, but I figured that was pretty unnecessary.
Thanks!
Variable names are compile-time artifacts. They don't exist at runtime. It doesn't make sense in C++ to create a dynamically-named variable. How would you refer to it?
Let's say you had this hypothetical create function, and wrote code like:
create("reg");
reg.value = 5;
This wouldn't compile, because the compiler doesn't know what reg refers to in the second line.
C++ doesn't have any way to look up variables at runtime, so creating them at runtime is a nonstarter. A hash table is the right solution for this. Store objects in the hash table and look them up by name.
This isn't possible. C++ does not offer any facilities to process code at runtime. Given the nature of a typical C++ implementation (which compiles to machine code ahead of time, losing all information about source code), this isn't even remotely feasible.
Like I said in my comment:
What's the point? A variable name is something the compiler, but -most importantly- you, the programmer, should care about. Once the application is compiled, the variable name could be whatever... it could be mangled and senseless, it doesn't matter anymore.
You read/write code, including var-names. Once compiled, it's down to the hardware to deal with it.
Neither C nor C++ have eval functions
Simply because: you only compile what you need, eval implies input later-on that may make no sense, or require other dependencies.
C/C++ are compiled ahead of time, eval implies evaluation at runtime. The C process would then imply: pre-process, compile and link the string, in such a way that it still is part of the current process...
Even if it were possible, eval is always said to be evil, that goes double for languages like the C family that are meant to run reliably, and are often used for time-critical operations. The right tool for the job and all that...
A HashTable with objects that have hash, key, Register, collision members is the sensible thing to do. It's not that much overhead anyway...
Still feel like you need this?
Look into the vast number of scripting languages that are out there. Perl, Python... They're all better suited to do this type of stuff
If you need some variable creation and lookup you can either:
Use one of the scripting languages, as suggested by others
Make the lookup explicitly, yourself. The simplest approach is by using a map, which would map a string to your register object. And then you can have:
std::map<const char*, Register*> table;
Register* create(const char* name) {
Register* r = new Register();
table[name] = r;
return r;
}
Register* lookup(const char* name) {
return table[name];
}
void destroy(const char* name) {
delete table[name];
table.erase(name);
}
Obviously, each time you want to access a variable created this way, you have to go through the call to lookup.
I'm parsing .h and .cpp files and I need to find/replace all non-Hungarian notated variables with their Hungarian equivalents. "Augh, why?!" you ask? My employer requires Hungarian notation, 'nuff said.
Let's just deal with ints for now.
Given any of these cases...
int row; // no hungarian prefix
int nrow(9); // incorrect capitalization
int number; // hmm...
int nnumber = getValue(); // uh oh!
They should be changed to:
int nRow;
int nRow(9); // obviously ctor args and assignments shouldn't change
int nNumber;
int nNumber = getValue();
I'm shooting for just a single one-line call to s/// ideally.
For added challenge, if someone can get something to change ALL instances of this variable after the "type check" with int, that would earn you some brownie points.
Here's what I have so far:
s/(int\s+)(?!n)(\w+)/$1n\u$2/g;
This doesn't match things like int nrow or int number though.
Thanks in advance!
No.
More explicitly, you are trying to compile a program using a regex. This does not work that way.
For example, your one-line already forgets of function parameters, and it cannot parse any user defined type (struct, enum). Not to mention that .cpp suggests C++ suggest classes.
Also, what happens with method / function / inline comments?
My advice would be find somewhere a grammar compiler and pass it the c++ grammar, so for every definition you get the value and type written down to a file. Then you can have regex fun with it. You may try also to write every time each variable is used in order to replace them later automatically.
Yet a lot more complex that a simple regex, but that simple regex will fail so much that at the end you will be changing the code manually.
As a positive note, maybe when you tell your boss how much the chane does cost maybe he will think about it better.
At a previous employer, we were writing binary messages that had to go "over the wire" to other computers. Each message had a standard header something like:
class Header
{
int type;
int payloadLength;
};
All of the data was contiguous (header, immediately followed by data). We wanted to get to the payload given that we had a pointer to a header. Traditionally, you might say something like:
char* Header::GetPayload()
{
return ((char*) &payloadLength) + sizeof(payloadLength);
}
or even:
char* Header::GetPayload()
{
return ((char*) this) + sizeof(Header);
}
That seemed kind of verbose, so I came up with:
char* Header::GetPayload()
{
return (char*) &this[1];
}
It seems rather disturbing at first, possibly too odd to use -- but very compact.
There was a lot of debate on whether it was brilliant or an abomination.
So which is it - Crime against coding, or nice solution? Have you ever had a similar trade-off?
-Update:
We did try the zero sized array, but at the time, compilers gave warnings.
We eventually went to the inhertited technique: Message derives from Header.
It works great in practice, but in priciple you are saying a message IsA Header - which seems a little awkward.
I'd go for crime against coding.
Both methods will generate the exact same object code. The first makes it's intention clear. The second is very confusing, with the only advantage that it saves a couple keystrokes. (Just learn to freakin' type).
Also, note that NEITHER method is guaranteed to work. The sizeof() an object includes padding for word alignment, so that if the header was:
class Header
{
int type;
int payloadLength;
char status;
};
Both methods you describe would have the payload starting at Header+12, when most likely it actually starts at Header+9.
You're depending on the compiler to layout your classes in a particular way. I would have defined the message as a struct (with me defining layout) and had a class that encapsulates the message and provides the interface to it. Clear code = good code. "Cute" code = bad (hard to maintain) code.
struct Header
{
int type;
int payloadlength;
}
struct MessageBuffer
{
struct Header header;
char[MAXSIZE] payload;
}
class Message
{
private:
MessageBuffer m;
public:
Message( MessageBuffer buf ) { m = buf; }
struct Header GetHeader( )
{
return m.header;
}
char* GetPayLoad( )
{
return &m.payload;
}
}
It's been awhile since I've written any C++, so please excuse any issues with syntax. Just trying to convey the general idea.
Personally I think that if there's a crime, it's asking the header for the payload.
But as long as you're going to do it that way, 'this+1' is as good a way as any.
Justification: '&this[1]' is a general-purpose piece of code that doesn't require you to go digging through class-definitions to fully comprehend, and doesn't require fixing when someone changes the name or contents of the class.
BTW, the first example is the true crime against humanity. Add a member to the end of the class and it'll fail. Move the members around the class and it'll fail. If the compiler pads the class, it'll fail.
Also, if you're going to assume that the compiler's layout of classes/structs matches your packet layout, then you should understand how the compiler in question works. Eg. on MSVC you'll probably want to know about #pragma pack.
PS: It's a little scary how many people consider "this+1" or "&this[1]" hard to read or understand.
It's a common problem, but what you actually want is this.
class Header
{
int type;
int payloadLength;
char payload[0];
};
char* Header::GetPayload()
{
return payload;
}
My vote is Coding Horror. Don't get me wrong, it's clever - but you're saving yourself one entire addition operation at the cost of making the code much more difficult to understand and read. I don't see the tradeoff as worth it.
I think this is flawed from the start on if the header needs to "return" data which is not included in it.
As you already put yourself on these hackish grounds, I really love what you came up with.
But note that this is not a beauty contest. You should find an entire different solution. For alle the three versions of GetPayload() you presented, I would not understand what the hell is going on there without your further explanation.
Have you considered the 'empty array member' trick? I remember seeing it often, and even using it once or twice, but I can't seem to find any really good references (except, maybe, the one referenced below).
The trick is to declare your struct as
struct bla {
int i;
int j;
char data[0];
}
Then, the 'data' member simply points to whatever is behind the headers. I am not sure how portable this is; I've seen it with '1' as the array size as well.
(using the URL below as a referece, using the '[1]' syntax, seemed not to work because it is too long. Here is the link:)
http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/gcc/Zero-Length.html
If it works -- consistently -- then it's an elegant solution.
It will normally work in memory because the compiler will deal with alignment issues and you can assume that the Payload follows the header in correctly-aligned memory space.
I could see this falling apart when the Header/Payload objects are streamed "over the wire" because the streaming mechanism you use will probably not care about aligning objects on any particular boundary. Therefore, Payload may directly follow the Header with no padding to force it to a particular alignment.
To coin a phrase, elegant is as elegant does. So, it's elegant as long as you are careful how you stream it.
First, there's an awful lot of space between "crime against coding" and "nice solution," but I'd say this is closer to the former.
Is the Header its Payload's keeper?
That's the fundamental problem here -- both the header and the payload should be managed by another object that holds the entire message, and that is the proper place to ask for the payload. And it would be able to do so without pointer arithmetic or indexing.
Given that, I would favor the second solution, since it is clearer what is going on.
But that we're in this situation to begin with seems to indicate that the culture of your team values cleverness over clarity, so I guess all bets are off.
If you really want to be cute, you could generalize.
template<typename T. typename RetType>
RetType JustPast(const T* pHeader)
{
return reinterpret_cast<RetType>(pHeader + sizeof(T));
}
They're basically the same thing as far as I'm concerned. Both are forms of byte juggling, which is always risky, but not impossible to get right.
The first form is a bit more accepted and recognizable.
I would personally write :
char* Header::GetPayload()
{
return ((char*) this) + sizeof(*this);
}
Don't forget that VC++ may impose a padding on the sizeof() value on the class. Since the provided example is expected to be 8 bytes, it is automatically DWORD aligned, so should be ok. Check #pragma pack.
Though, I agree, the provided examples are some degree of Coding Horror. Many Win32 data structures include a pointer placeholder in the header structure when variable length data follows. This is probably the easiest way to reference this data once it's loaded into memory. The MAPI SRowSet structure is one example of this approach.
I actually do something similar, and so does nearly every MMO or online video game ever written. Although they have a concept called a "Packet" and each packet has it's own layout. So you might have:
struct header
{
short id;
short size;
}
struct foo
{
header hd;
short hit_points;
}
short get_foo_data(char *packet)
{
return reinterpret_cast<foo*>(packet)->hit_points;
}
void handle_packet(char *packet)
{
header *hd = reinterpret_cast<header*>(packet);
switch(hd->id)
{
case FOO_PACKET_ID:
short val = get_foo_data(packet);
//snip
}
}
And they do that for the majority of their packets. Some packets obviously have dynamic sizes, and for those members they use length prefixed fields and some logic to parse that data.
I think in this day and age, in C++, the C-style cast to char* disqualifies you from any "brilliant design idea" awards without getting much of a hearing.
I might go for:
#include <stdint.h>
#include <arpa/inet.h>
class Header {
private:
uint32_t type;
uint32_t payloadlength;
public:
uint32_t getType() { return ntohl(type); }
uint32_t getPayloadLength() { return ntohl(payloadlength); }
};
class Message {
private:
Header head;
char payload[1]; /* or maybe std::vector<char>: see below */
public:
uint32_t getType() { return head.getType(); }
uint32_t getPayloadLength() { return head.getPayloadLength(); }
const char *getPayload() { return payload; }
};
This assumes C99-ish POSIX, of course: to port to non-POSIX platforms you'd have to define one or both of uint32_t and ntohl yourself, in terms of whatever the platform does offer. It's usually not hard.
In theory you might need layout pragmas in both classes. In practice I'd be surprised given the actual fields in this case. The issue can be avoided by reading/writing the data from/to iostreams one field at a time, rather than trying to construct the bytes of the message in memory and then write it in one go. It also means you can represent the payload with something more helpful than a char[], which in turn means you won't need to have a maximum message size, or mess about with malloc and/or placement new, or whatever. Of course it introduces a bit of overhead.
Perhaps you should have used a verbose method, but replaced it with a #define macro? This way you can use your shorthand when typing, but anyone needing to debug the code can follow along without issue.
I vote for &this[1]. I've seen it used quite a bit when parsing files that have been loaded into memory (which can equally include received packets). It may look a tad odd the first time you see it, but I think that what it means should be immediately obvious: it's clearly the address of memory just past this object. It's nice because it's hard to get wrong.
I don't like to use words like "crime". I would rather point out that &this[1] seems to make assumptions about memory layout that a compiler might disagree with. For example, any compiler might, for its own reasons (like alignment), insert dummy bytes anywhere in a structure. I would prefer a technique that has more of a guarantee of getting the correct offset if compilers or options get changed.
In addition to the abovementioned, I'd say that this is a crime against interoperability and good wire protocol design principles. It is really surprising how many programmers are not able/willing to make a clear distinction between a wire protocol definition and its implementation.
If your protocol has to survive for more than two days, it most probably has to survive for more than two years/OSes/compilers/languages/endiannesses and in some point it will break, rather sooner than later. So, make other folks' life easier, write down the wire protocol specification plus write proper (de)serialization routines. Otherwise, people will keep mentioning your name in not so pleasant contexts.