|
Boost : |
From: Noel Yap (Noel.Yap_at_[hidden])
Date: 2003-05-05 08:19:51
"Justin M. Lewis" wrote:
> It DOES affect the caller, since x was modified internally inside f.
>
> int & f(int &x)
> {
> x++;
> return(x);
> }
>
> int x;
> int &y = f(x);
>
> What indication is there that x was changed inside of f?
I see, you're right. Rather than the current proposal, why not:
int x;
int& y = f( in( x ) ); // x isn't changed, but not so great since f owns the return value
int x;
int& y = f( in_out( x ) ); // x can be changed, but not se great since f owns the return value
Or, IMHO, better still since only one new class is introduced:
int x;
int y = f( dumb_ref< int const >( x ) ); // x isn't changed, return value is a cheap copy
int x;
int y = f( dumb_ref< int >( x ) ); // x may be changed, return value is a cheap copy
> int * f(int *x)
> {
> *x++;
> return(x);
> }
>
> int x;
> int *y = f(&x);
>
> Again, what indication is there that x was modified internally?
The fact that the writer of the function decided to have a pointer passed in. It sounds like you're not aware of this convention. Aside from disallowing NULL, the proposed classes won't be any different -- it'll be a convention.
> How do I
> know that what's being returned isn't being allocated by f?
Because the pointer is being passed by value. If f were intended to allocate something new, one could do either of:
void f( T** x );
std::auto_ptr< T > f(); // this is much clearer than the above
> You can't tell
> just by looking at the call, you have to go track down the definition of the
> function.
No, you don't; they're equivalent:
void f( in_out< T > p_ ); // indicates p_ may be changed, NULL not allowed
void f( T* p_ ); // indicates p_ may be changed, NULL allowed
> Like I've said, the system does require that the programmer use the objects
> properly. BUT, assuming they are used properly, just like we assume that
> when we pass a const object it's not being const_cast, then it tells you for
> sure that f is dependent on the value inside x and y, so they have to be
> initialized to something, AND, it tells you that the values in x and y may
> change.
Right; it's a convention just like all the other existing ones. I think the value added is that it's clear at the call site what the function signature is. OTOH, there are other ways of achieving this.
> Our definitions of c_in are different, I'm using bad naming in this regard,
> it should be something that indicates that ownership of the object is
> changing hands. For your version of c_in, I wouldn't want the common case
> to have to be decorated. In only params are the most common.
If ownership changes hands, either a copy is necessary, or dynamic memory is necessary:
f( T in_ ); // pass by value
f( std::auto_ptr< T > in_ ); // pass ownership of memory in
> void f(const CObj &o)
> {
> cout << o << endl;
> }
>
> Something like that, I think that's your version of an in param.
Yes, exactly. It's passed in, but changes don't get passed back out.
> I wouldn't
> want to have to decorate all of those. I want the ones that are the odd
> case decorated, so it's explicit that, hey, this isn't the common case, this
> function IS going to modify these parameters, so heads up.
We're still left with in_out<> in this case:
void f( T const& in_ );
void f( in_out< T > inOut_ );
Since out acts just like in_out<> but is just syntactic sugar:
template< typename T >
class out:
public in_out< T >
{
};
Noel
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk