M
markspace
Hi all,
I saw a great idea the other day. You can read about it here:
http://amitp.blogspot.com/2004/04/c-references-vs-pointers.html
Basically, Amit has this receivable class (template, actually) that
allows you to mark which function parameters are being modified, for
easier reading.
His class is defined here:
template<typename T>
struct receivable {
explicit receivable(T& receiver): receiver_(receiver) {}
T& get() { return receiver_; }
operator T& () { return receiver_; }
T& operator = (const T& v) { receiver_ = v; return receiver_; }
private:
T& receiver_;
};
and he gives the following example of it's use:
void f(receivable<int> i) {
i = 5;
}
int main() {
int j;
f(j); // this line causes a compile-time error
f(receive(j)); // this line works
}
Ok, so far so good. *But*, the example does't compile, because the word
"receive" isn't defined. (Not because of the line that says "this line
causes a compile-time error", yes I was smart enough to comment that out
first. ) So I'm confused, and I thought I'd ask here about it.
What I got to work is "f(receivable<int>(j));" This runs correctly, and
is only a bit more wordy. I'm not very good at reading class definitions
though, and determining all the ways to use that class, so I have a few
questions.
First, is there a better way to convert j to a receivable class?
What, for example does "operator T& () { return receiver_; }" do? Is
that a type conversion or cast? How the heck do I use it?
What the heck is get()? Is this just for converting a receivable to
it's base(?) type? Like:
void f(receivable<int> i) {
i = 5;
std::cout << i.get() << std::endl;
}
Lastly, operator= seems clear enough. But the const bit confuses me.
Is there a case where the right hand expression of an assignment would
*not* be const? It seems like there couldn't be...
And here's my own little observation: The receivable class is similar
to the practice of #define OUT and IN to be nothing, allowing a
programmer to mark parameters as changable or not:
#define OUT
#define IN
void f(OUT int& i, IN int k) {
i = k;
}
int main() {
int j;
f(OUT j, IN 3); // cheesy, OUT does nothing
}
But if one renames the receivable class to OUT, you can do this:
void f(OUT<int> i, IN int k) {
i = k;
}
int main() {
int j;
f(OUT<int>(j), IN 3); // better...
}
And it's less typing too.
I saw a great idea the other day. You can read about it here:
http://amitp.blogspot.com/2004/04/c-references-vs-pointers.html
Basically, Amit has this receivable class (template, actually) that
allows you to mark which function parameters are being modified, for
easier reading.
His class is defined here:
template<typename T>
struct receivable {
explicit receivable(T& receiver): receiver_(receiver) {}
T& get() { return receiver_; }
operator T& () { return receiver_; }
T& operator = (const T& v) { receiver_ = v; return receiver_; }
private:
T& receiver_;
};
and he gives the following example of it's use:
void f(receivable<int> i) {
i = 5;
}
int main() {
int j;
f(j); // this line causes a compile-time error
f(receive(j)); // this line works
}
Ok, so far so good. *But*, the example does't compile, because the word
"receive" isn't defined. (Not because of the line that says "this line
causes a compile-time error", yes I was smart enough to comment that out
first. ) So I'm confused, and I thought I'd ask here about it.
What I got to work is "f(receivable<int>(j));" This runs correctly, and
is only a bit more wordy. I'm not very good at reading class definitions
though, and determining all the ways to use that class, so I have a few
questions.
First, is there a better way to convert j to a receivable class?
What, for example does "operator T& () { return receiver_; }" do? Is
that a type conversion or cast? How the heck do I use it?
What the heck is get()? Is this just for converting a receivable to
it's base(?) type? Like:
void f(receivable<int> i) {
i = 5;
std::cout << i.get() << std::endl;
}
Lastly, operator= seems clear enough. But the const bit confuses me.
Is there a case where the right hand expression of an assignment would
*not* be const? It seems like there couldn't be...
And here's my own little observation: The receivable class is similar
to the practice of #define OUT and IN to be nothing, allowing a
programmer to mark parameters as changable or not:
#define OUT
#define IN
void f(OUT int& i, IN int k) {
i = k;
}
int main() {
int j;
f(OUT j, IN 3); // cheesy, OUT does nothing
}
But if one renames the receivable class to OUT, you can do this:
void f(OUT<int> i, IN int k) {
i = k;
}
int main() {
int j;
f(OUT<int>(j), IN 3); // better...
}
And it's less typing too.