Re: [boost] Re: Re: class proposal
Terje Slettebø wrote: > The part about RVO was really concerned with the out() scenario, not > in_out(). I'm not sure if passing a smart pointer buys you very much. In > this case, the smart pointer is const but the pointee is not, so the "const" > in the signature is really just masking what is going on. You're right. I see your point. At first I thought that if there were an easy way to convert smart_ptr< T > to smart_ptr< T const > there'd be no problem. But then I realized this would bring about the expensive copy again. IMHO, the solution to this dilemna is to use the de facto standard way of using references like you said earlier: void f( T& value_may_change_, T const& value_may_not_change_ ); Noel -- NOTICE: If received in error, please destroy and notify sender. Sender does not waive confidentiality or privilege, and use is prohibited. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: class proposal
>From: "Noel Yap" <[EMAIL PROTECTED]> > Terje Slettebø wrote: > > The compiler may elide such copy, even if the temporary being returned is a > > named variable, and several compilers (such as g++ and the EDG based ones), > > does this optimisation (RVO). For example: > > Playing devil's advocate, I think RVO can easily be fooled with > not-so-tricky code. If you're really concerned about this situation, > use some sort of smart pointer. For example: > > boost:shared_ptr< T > f( boost::shared_ptr< T > const in_ ); The part about RVO was really concerned with the out() scenario, not in_out(). I'm not sure if passing a smart pointer buys you very much. In this case, the smart pointer is const but the pointee is not, so the "const" in the signature is really just masking what is going on. Furthermore, this means dynamical allocation (either by caller or callee), which may be more expensive than making a copy on the stack (unless it's elided), and passing that. Yes, there are ways to write it so that RVO is disabled, but with careful coding for this, such as using single exit, you can enable it, and it can be tested for. Regards, Terje ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: class proposal
Terje Slettebø wrote: > The compiler may elide such copy, even if the temporary being returned is a > named variable, and several compilers (such as g++ and the EDG based ones), > does this optimisation (RVO). For example: > > Playing devil's advocate, I think RVO can easily be fooled with not-so-tricky code. If you're really concerned about this situation, use some sort of smart pointer. For example: boost:shared_ptr< T > f( boost::shared_ptr< T > const in_ ); Noel ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: class proposal
Just to add some to my previous posting. Also, from a maintenance POV, having variables that doesn't change throughout a function (or program), tends to make it easier to understand. Having functions which change their arguments goes rather against that. One exception is input stream operators, where it's really no other way of doing it than first declaring a variable, then streaming into it. For example: const some_type valueA=...; const some_type valueB = f(valueA); // Possibly many lines of code here // What is valueA and valueB here? Answer: The same as when they were declared. Yes, I know it may be a massive undertaking to start making a program, which wasn't designed that way, const correct. However, it may be one of the better refactorings to do. It also highlights all the points where something may be changed, and where further refactorings (such as those in the previous posting) may be appropriate. Regards, Terje ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: class proposal
>From: "Justin M. Lewis" <[EMAIL PROTECTED]> > As for a function returning a single param, I agree, normally you'd just > return it, UNLESS it's some big structure you don't want being copied > all over the place, then passing it by reference to a function makes > more sense. The compiler may elide such copy, even if the temporary being returned is a named variable, and several compilers (such as g++ and the EDG based ones), does this optimisation (RVO). For example: class big_class { ... }; big_class f(...) { big_class temp; ... return temp; } // Only the constructor is called, here, no copy constructor big_class value = f(...); Also, if you want to return multiple values, std::pair or boost::tuple may be used for that, as Noel Yap pointed out. I understand the motivation is to transform a lot of existing code into something that may be more easily understood. However, an alternative to your method is to use techniques that has been proposed in this thread. For example: int return_value = f(type &may_change, const type &may_not_change); // Current function int return_value = fA(c_out may_change, const type &may_not_change); // Your method boost::tuple fB(const type &may_not_change); // Alternative Use: type value; int return_value = fA(out(value), const_value); // Your method int return_value; boost::tie(return_value, value) = fB(const_value); Also, you may enforce that the parameters aren't changed, by using const: const type const_value = ...; fA(const_value, ...); // Error, can't bind to non-const reference This may be a larger refactoring than adding out() and in_out(), though, especially for a large code base, as you mention. I'm just concerned with that out() and in_out() isn't a very common way to do it, so it may be best to do it in an idiomatic way, to begin with. Also, statements like: boost::tie(return_value, value) = fB(const_value); stands out in the code, rather than being more hidden with an out(). Thus, they may have a better chance of being possibly further refactored. Say that the return code says whether or not a valid object is returned. This may be changed to: boost::optional result = fB(const_value); Or maybe throwing an exception would be more appropriate: type value = fB(const_value); // Throws on failure The point really is the same as with your proposal - making it explicit in the code what is happening. Regards, Terje ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Re: Re: class proposal
It's not always that easy to give a function a name that will tell you at invocation time which of it's parameters it's planning on changing, and, it would be hard to tell people through just a function name that a parameter is an in/out parameter. As for a function returning a single param, I agree, normally you'd just return it, UNLESS it's some big structure you don't want being copied all over the place, then passing it by reference to a function makes more sense. Or, in the case I originally created this for, I had a function that initialized an object to begin a transaction, I wanted to pass an object into my function, and have it properly initialized to start a transaction. Anyway, in that case, InitRequest makes it pretty clear that the object being passed is going to be modified, but by making it a c_out param, there's NO question, it's explicit at the invocation. -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Bo Persson Sent: Wednesday, April 23, 2003 11:32 AM To: [EMAIL PROTECTED] Subject: [boost] Re: Re: class proposal "Justin M. Lewis" <[EMAIL PROTECTED]> skrev i meddelandet news:[EMAIL PROTECTED] > Not entirely, passing a pointer doesn't tell you that the parameter will > change, it just tells you that it might, it still leaves you in the position > of having to track down the function and check it. But outside of that, if > you're like me, at this point you prefer references to pointers, whenever > possible. The obvious solution is of course to name the function so that you can tell what is does! :-) A function returning a single value, should really RETURN the value and not update a parameter: y = year_of_first_marriage(); Having a function lying about its purpose should be caught at its definition, not at each call of the function: void will_never_change_any_parameters_honest(int& x) { x = 7; } is easy to catch early. :-) Bo Persson [EMAIL PROTECTED] > > - Original Message - > From: "Vincent Finn" <[EMAIL PROTECTED]> > To: <[EMAIL PROTECTED]> > Sent: Wednesday, April 23, 2003 2:09 AM > Subject: [boost] Re: class proposal > > > > > > > > void func(int &x){x = 1977;}; > > > > > > void blah() > > > { > > > int y=0; > > > func(y); > > > func2(y); > > > printf("%d\n", y); > > > } > > > ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: class proposal
"Justin M. Lewis" <[EMAIL PROTECTED]> skrev i meddelandet news:[EMAIL PROTECTED] > Not entirely, passing a pointer doesn't tell you that the parameter will > change, it just tells you that it might, it still leaves you in the position > of having to track down the function and check it. But outside of that, if > you're like me, at this point you prefer references to pointers, whenever > possible. The obvious solution is of course to name the function so that you can tell what is does! :-) A function returning a single value, should really RETURN the value and not update a parameter: y = year_of_first_marriage(); Having a function lying about its purpose should be caught at its definition, not at each call of the function: void will_never_change_any_parameters_honest(int& x) { x = 7; } is easy to catch early. :-) Bo Persson [EMAIL PROTECTED] > > - Original Message - > From: "Vincent Finn" <[EMAIL PROTECTED]> > To: <[EMAIL PROTECTED]> > Sent: Wednesday, April 23, 2003 2:09 AM > Subject: [boost] Re: class proposal > > > > > > > > void func(int &x){x = 1977;}; > > > > > > void blah() > > > { > > > int y=0; > > > func(y); > > > func2(y); > > > printf("%d\n", y); > > > } > > > ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost