Go Back   Rhinocerus > Newsgroup > Newsgroup comp.language.c++ > Newsgroup comp.language.c++.moderated

Reply
 
Thread Tools Display Modes
  #16 (permalink)  
Old 04-12-2012, 10:05 AM
rossmpublic@gmail.com
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On Tuesday, April 10, 2012 11:14:08 AM UTC-7, Alf P. Steinbach wrote:
> The compiler is able to do it within the current language, but it's
> constrained by
>
> * the problem of aliasing, i.e. correctness violation, and
>
> * depending on the solution, a combinatorial explosion, and that
>
> * depending on the solution, the linker must support the scheme.


Thanks for the analysis Alf. On the surface it looks like the
separate compilation model sinks attempts to provide input value
optimization as Dave Abrahams mentioned. But perhaps a really robust
compiler/linker would be able to do it?

Here's what I've been thinking. Let's start with something simple:

- Only apply optimization to classes with non trivial constructors
or POD classes of a certain size. To avoid pessimizations.

- Restrict candidates for this optimization to parameters
that are only copied inside the function.

- If the parameter is passed by reference to any function (including
constructors) it cannot be optimized. Perhaps we may want to
allow const references for an aggressive optimization strategy but
this would not be strictly correct/conforming.

- The goal is to guarantee that when the function exits that the
parameter will not be modified if it is passed by reference.
Therefore we can create a single optimized version of the function
call and avoid the combinatorial explosion. Alf?

- Now the hand-waving part! Somehow when the linker mashes the
entire executable together it needs to substitute the non-optimized
calls to the optimized ones. I need some help on this part.


I'll add an additional observation at this point:

This optimization will never work for virtual function calls,
so the pass by reference hand optimization may never be completely
eliminated from the language.


> A partial solution, to avoid all three of those problems, is to use
> immutable types with reference semantics.


Can you elaborate a little more on this point? Do you mean that if we
had a concept of an immutable class that the compiler could recognize
then we could more easily apply copy optimizations?


> Also, for the particular case of `std::string` another partial solution
> is to use a COW (Copy On Write) implementation, which I believe is still
> how the implementation for g++ works.


Maybe we just need copy on write objects? This may solve some copying
issues.

Is there anyway that std::move can help us here? For instance, can the
temporary parameter object be moved to my member variable in my class
constructor?

--
Ross MacGregor


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #17 (permalink)  
Old 04-12-2012, 10:18 AM
Geert-Jan Giezeman
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On 04/10/2012 08:00 PM, Ulrich Eckhardt wrote:
> Am 10.04.2012 11:18, schrieb rossmpublic@gmail.com:
>> I have a very simple question that I have been unable to find a
>> satisfactory answer. The question is why do I need to manually
>> optimize my functions using const references?
>>
>> For example:
>>
>> // Optimized passing of string parameter
>> Widget(std::string const& name);
>> SetName(std::string const& name);
>>
>> // Non-optimized passing of string parameter
>> Widget(std::string name);
>> SetName(std::string name);

>
> Even worse:
>
> // optimized passing of int parameter
> void foo(int i);
> // pessimized passing of int parameter
> void foo(int const& i);
> // probably pessimized passing of pair
> void bar(std:air<int, int> const& p);
> // and what about this here??
> SetName(std::string name) { this->name.swap(name); }
>
> The performance of course depends on the actual implementation, but in
> common implementations a reference is just a "self-dereferencing
> pointer", so a reference requires another level of indirection. Also,
> any function can cheat and const_cast, so a calling function must not
> assume that the call doesn't modify the passed object. Making informed
> predictions requires looking at the implementation of the function,
> which is the reason that many modern compiler perform optimizations
> across translation-unit boundaries.
>
> Note that the thing with the int and pair above is something I learned
> from micro-optimizing some code. Certain code. On one particular
> platform. In a very tight loop. I don't claim that this is universally
> the most performant way.


The compiler knows best what is the most efficient way of passing a
value. The programmer knows best if passing by const reference is OK as
a possible optimisation. So, a possibility would be to invent some
syntax to tell the compiler to pick the most efficient method of passing
a value either by value or by const reference. E.g.

void foo(int default i)
// probably equivalent to: void foo(int i)
void foo(std::string default s)
// probably equivalent to: void foo(std:string const &s)
void foo(std:air<int, int> default p)
// may depend on the platform how the pair is passed


Geert-Jan Giezeman


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #18 (permalink)  
Old 04-12-2012, 07:42 PM
Alf P. Steinbach
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On 12.04.2012 12:05, rossmpublic@gmail.com wrote:
> On Tuesday, April 10, 2012 11:14:08 AM UTC-7, Alf P. Steinbach wrote:
>> The compiler is able to do it within the current language, but it's
>> constrained by
>>
>> * the problem of aliasing, i.e. correctness violation, and
>>
>> * depending on the solution, a combinatorial explosion, and that
>>
>> * depending on the solution, the linker must support the scheme.

>
> Thanks for the analysis Alf. On the surface it looks like the
> separate compilation model sinks attempts to provide input value
> optimization as Dave Abrahams mentioned. But perhaps a really robust
> compiler/linker would be able to do it?


With the flags approach that I described you don't need additional
linker support.

But it might be premature optimization.

It could be that at least for some programs it would, in total, slow
things down to pass those flags everywhere, e.g. because one less
register was available, or whatever.

> Here's what I've been thinking. Let's start with something simple:
>
> - Only apply optimization to classes with non trivial constructors
> or POD classes of a certain size. To avoid pessimizations.
>
> - Restrict candidates for this optimization to parameters
> that are only copied inside the function.
>
> - If the parameter is passed by reference to any function (including
> constructors) it cannot be optimized. Perhaps we may want to
> allow const references for an aggressive optimization strategy but
> this would not be strictly correct/conforming.


Wrt. passing further to some reference to const formal argument, the
main solution to the problem that the compiler can't guarantee the one
in a trillion trillion'th case in Very Bad Code, is to let the
programmer take responsibility. Leave the programmer in control. Much
is impossible if the compiler must do it all alone, because, well, if
it was outfitted with the necessary smarts then it would be very much
too slow! But with a little help from the programmer, which is what
many of the keywords in C++ are about, very little remains as
impossible. E.g. in this case the help could take the form of some
attribute which, if present, prevents the optimization, e.g. because
there's a call to a function that modifies in spite of promising not
to.

Of course, it would then be a kind of absurd situation where one
programmer is adding an attribute saying that another programmer (or
possibly him/her self) incorrectly added "const" to some formal arg.

Anyway, with such a more practical solution (programmer decides in
dubious case) the "cannot be optimized" is happily not correct. And
likewise, "would not be correct" is then happily not correct. It can
be optimized, and it will be correct, just not wrt. the current
language.

With the absence of an attribute taken as general leave to optimize,
an argument of type "cv T" is a candidate for optimization if, say,
the Boost function that produces good argument types changes the
type. Then furthermore there must be no potential modification of that
argument, under the assumption (provided by absence of attribute) that
"const" really means "not modified". Under these conditions the
optimization is permitted for that argument. Whether copying will
actually be done in any particular call, then depends on the
corresponding flag passed by the caller. If the call site promises via
this argument's flag that there is no possible aliasing, then copying
will be avoided. And what's nice about that is that the caller can
pass those flags also to a non-optimized function, which then will
copy regardless of the flags. I.e. each call site does not need to
know whether the function implementation supports the optimization or
not -- each call site's responsibility is just to decide whether it
can guarantee non-aliasing.


> - The goal is to guarantee that when the function exits that the
> parameter will not be modified if it is passed by reference.
> Therefore we can create a single optimized version of the function
> call and avoid the combinatorial explosion. Alf?


Oh yes, that's simple, as I wrote.

Instead of different variants of function, just a single function with
a hidden flags argument.

Where the flags carry each call site's knowledge of aliasing, into the
function.


> - Now the hand-waving part! Somehow when the linker mashes the
> entire executable together it needs to substitute the non-optimized
> calls to the optimized ones. I need some help on this part.


Huh.


> I'll add an additional observation at this point:
>
> This optimization will never work for virtual function calls,
> so the pass by reference hand optimization may never be completely
> eliminated from the language.


As an exercise, imagine the optimization is done, with the flags
approach.

Then it just works.


>> A partial solution, to avoid all three of those problems, is to use
>> immutable types with reference semantics.

>
> Can you elaborate a little more on this point? Do you mean that if we
> had a concept of an immutable class that the compiler could recognize
> then we could more easily apply copy optimizations?


With immutable types with reference semantics there is no copying
(except of small pointer). Think Java strings. You can reassign a Java
string variable, but that doesn't copy the string value.

Neither is there any modification of the string value.

So, the problem is then just not relevant.


>> Also, for the particular case of `std::string` another partial
>> solution is to use a COW (Copy On Write) implementation, which I
>> believe is still how the implementation for g++ works.

>
> Maybe we just need copy on write objects? This may solve some copying
> issues.


Scott Meyers, I think it was, recently remarked that COW is not
permitted for std::string under C++11 rules.

I'm not sure if that's correct, but with threading in the picture it
sounds quite plausible.

The nice thing about one's own types is that they can be more
practical wrt. safety, at least with 20-20 hindsight. Where
std::string is needlessly unsafe (e.g. construction from 0), one's own
type can be safe, and where std::string (reportedly) has to support
safe operations in some kind of multi-thread scenario, I don't know
exactly what but something that affects COW, one's own type can just
happily and more practically pass the problem on to the
programmer. Don't use me that way, or else add synchronization!

> Is there anyway that std::move can help us here? For instance, can the
> temporary parameter object be moved to my member variable in my class
> constructor?


I'm not sure that I understand that question.


Cheers & hth.,

- Alf


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #19 (permalink)  
Old 04-12-2012, 07:44 PM
James K. Lowden
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On Thu, 12 Apr 2012 03:18:04 -0700 (PDT)
Geert-Jan Giezeman <geert@cs.uu.nl> wrote:

> So, a possibility would be to invent some
> syntax to tell the compiler to pick the most efficient method of
> passing a value


Done. it's called "C++".

The standard afaik imposes no machine-code restriction on function
call implementation. Anything that adheres to the semantics it defines
is valid.

--jkl


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #20 (permalink)  
Old 04-12-2012, 07:46 PM
James K. Lowden
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On Tue, 10 Apr 2012 11:14:08 -0700 (PDT)
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> wrote:

> Ideally there should
> be "in", "out" and "in-out" designators as in Ada


We almost have that now, right?

in: value or const reference
out: reference
in/out: reference

The last doesn't deserve distinction. It's rarely used because it's
rarely justified.

Were "in/out" syntax part of the language, the programmer has to learn
and use it, and the compiler has to enforce it. Yet it's hardly used.
For instance, there's barely one in/out parameter in the STL.
std::string::swap() is one uncommon example. I can't think of any that
don't involve some kind of similar buffer replacement. Nothing in
<algorithm> uses in/out parameters.

The best functions are true functions: one output generated from N
inputs. Sometimes, because of the way C++ is defined, the output takes
the form of an output parameter instead of a return type. (And
sometimes the return value is used to convey error status, but that's a
whole different discussion!) Functions with in/out parameters, by
contrast, have side-effects by design.

--jkl


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #21 (permalink)  
Old 04-12-2012, 07:49 PM
Martin B.
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On 12.04.2012 06:08, Dave Harris wrote:
> 0xCDCDCDCD@gmx.at (Martin B.) wrote (abridged):
>> However, what I would like to raise as a QOI question is, why can't
>> we have (or do we?) a proper compiler warning when the compiler
>> detects that the passed-by-value parameter isn't modified at all
>> and really should have been passed by const-reference?

>
> I would not want such a warning. There are too many cases where
> passing a copy is preferred.
>
> For example, passing an int by const reference is almost certainly
> worse for performance. So, probably, is passing a pair of ints, or a
> pair of pointers. If the warning depends on the size of the object,
> than making a class use the pImpl idiom could trigger the warning,
> as could other implementation changes.
>
> You should consider the issue of aliasing. It may be cheaper to pass
> a 4-int rectangle by const reference, but using it may be more
> expensive because it's harder for the compiler to be sure it is not
> changed through an alias.
>
> Another issue is the need for a standard interface, for
> polymorphism. Some overrides of a virtual function might change
> their arguments, and others might not.


All valid points!

Still, there are far too many cases in our code base where devs just
forget the "const&" where it would make perfectly sense.

I guess it may be too advanced for a compiler.

Would be interestng though if static analysis tools do such checking -
maybe on a class by class base or based on other configuration
options.

cheers,
Martin

--
Good C++ code is better than good C code, but
bad C++ can be much, much worse than bad C code.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #22 (permalink)  
Old 04-12-2012, 07:51 PM
Francis Glassborow
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On 12/04/2012 11:05, rossmpublic@gmail.com wrote:
> On Tuesday, April 10, 2012 11:14:08 AM UTC-7, Alf P. Steinbach wrote:
>> The compiler is able to do it within the current language, but it's
>> constrained by
>>
>> * the problem of aliasing, i.e. correctness violation, and
>>
>> * depending on the solution, a combinatorial explosion, and that
>>
>> * depending on the solution, the linker must support the scheme.

>
> Thanks for the analysis Alf. On the surface it looks like the
> separate compilation model sinks attempts to provide input value
> optimization as Dave Abrahams mentioned. But perhaps a really robust
> compiler/linker would be able to do it?
>
> Here's what I've been thinking. Let's start with something simple:
>
> - Only apply optimization to classes with non trivial constructors
> or POD classes of a certain size. To avoid pessimizations.
>
> - Restrict candidates for this optimization to parameters
> that are only copied inside the function.
>
> - If the parameter is passed by reference to any function (including
> constructors) it cannot be optimized. Perhaps we may want to
> allow const references for an aggressive optimization strategy but
> this would not be strictly correct/conforming.
>
> - The goal is to guarantee that when the function exits that the
> parameter will not be modified if it is passed by reference.
> Therefore we can create a single optimized version of the function
> call and avoid the combinatorial explosion. Alf?
>


Rgat last is not sufficient in multi-threaded/concurrent code. You
must also guarantee that the bject passed be reference is not modified
elsewhere during the execution of the function. I think that is a
more demanding requirement these days and would effectively require
the implementation to do much more analysis before optimising.

Note that an implementation can already do what you ask under the 'as
if' rule as long as it can demonstrate that the choice cannot be
detected by the program behaviour (other than efficiency)

Francis


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #23 (permalink)  
Old 04-13-2012, 08:50 AM
rossmpublic@gmail.com
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On Tuesday, April 10, 2012 11:14:08 AM UTC-7, Alf P. Steinbach wrote:
> Here is an example of aliasing at work:


Nice example. That code would break my naive solution as
I would have assumed that the input parameter wouldn't
be changing.

So are you saying that the compiler could detect a possible
problem with this parameter seeing how it is global (or maybe
a passed in reference) and choose not to optimize it at the
call site?

> Consider then that this binary choice is present for each sufficiently
> large argument where the optimization is relevant, and so that with n
> such arguments we're talking about 2^n implementation variants: a
> /combinatorial explosion/ akin to the one for perfect forwarding.


So you are saying:
- Sometimes you will want to apply the optimization and
sometimes not for various parameters of the same
function.
- We can implement this by defining N variations of the
function and link in the one we need at link time.

I can see how it may be implemented this way. However, I
am not entirely clear how the callee flags implementation
will work.

Do you mean that the function signature will use const
references for the optimized types and if the flag says pass
by value then an internal copy is made?

Are you suggesting putting the copy on the heap or stack?

How do you access the parameter/copy within the function?
Use an internal pointer? (Will cost an indirection for
pass by value parameters)
Checking flag before access? (Will cost for flag check)

--
Ross MacGregor


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #24 (permalink)  
Old 04-13-2012, 08:50 AM
rossmpublic@gmail.com
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

On Thursday, April 12, 2012 12:42:23 PM UTC-7, Alf P. Steinbach wrote:
> But with a little help from the programmer, which is what
> many of the keywords in C++ are about, very little remains as
> impossible. E.g. in this case the help could take the form of some
> attribute which, if present, prevents the optimization, e.g. because
> there's a call to a function that modifies in spite of promising not
> to.


In regard to extending the language: what if we annotate
class declarations?

We could specify if a class or struct should be passed
by value or by reference as the default behavior of the
function call optimizer. Then the developer will be in complete
control of the behavior. We will be able to say a class should
always be passed by value even if it were to contain a
non-trivial constructor!

A very simple implementation might even forgo the alias
checking and just rely on these types to never be aliased.
Probably not a recommended way to go but it would be an
option.

Likewise, a very simple implementation could even skip the
test inside the function to determine eligibility for
optimization. Parameters of pass-by-reference types will
always be passed by reference. Programmer beware.

This could also be a way to ensure no old code breaks
as only newly declared classes would participate in the
function call optimization.

It would be nice if we could expand the type system a bit
so that the following typedef would work:

typedef std::string by_ref rstring;

// Old C++
void Widget::set_name(std::string const & name)
{
this->name = name;
}

// Hand optimized free C++
void Widget::set_name(rstring name)
{
this->name = name;
}

// Hand optimized free C++
void set_name(rstring name)
{
name += ".xml"; // error: rsting is a constant type
this->name = name;
}

// Hand optimized free C++
void set_name(rstring name)
{
rsting new_name(name);
new_name += ".xml";
this->name = name;
}

--
Ross MacGregor


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #25 (permalink)  
Old 04-13-2012, 06:40 PM
P. Areias
Guest
 
Posts: n/a
Default Re: Why is there no input value optimization?

>
> In regard to extending the language: what if we annotate
> class declarations?
>



> typedef std::string by_ref rstring;
>
> // Old C++
> void Widget::set_name(std::string const & name)
> {
> this->name = name;
>
> }
>
> // Hand optimized free C++
> void Widget::set_name(rstring name)
> {
> this->name = name;
>
> }
>
> // Hand optimized free C++
> void set_name(rstring name)
> {
> name += ".xml"; // error: rsting is a constant type
> this->name = name;
>
> }
>
> // Hand optimized free C++
> void set_name(rstring name)
> {
> rsting new_name(name);
> new_name += ".xml";
> this->name = name;
>
> }



The explicit copy of arguments (when required) is the trademark of
Fortran (even 2003), since ALL arguments are passed by reference. C++
approach requires more discipline but In addition, the in / out /inout
safeguards are also in the intent() identification of arguments.

So it is either:

1) All (non-constant) references with explicit deep copies inside the
functions. Safeguards may be used: Fortran 95-2003
2) A variety of argument possibilities (in the end, pointers and
values). Copies are synthesized: C++
3) Possibly a VM to deal with more intricate situations. .NET

Wasn't B. Stroustrup intimately familiar with Fortran? I am also (cf.
SIMPLAS, SIMPLASMPC, etc) and prefer, for reasons of coding
efficiency, the C++ way. I never understood the need for C#, as it
seems less productive and more baroque than C++.

In my perspective, this was a difficulty of former Languages
definitely solved by the C++ syntax.

There are still some lacunae in C++ (I wonder why STATIC reflexion is
not in C++11 as any sufficiently complex program would benefit from it
sooner or later), but argument passing is not one (for mature
programmers.)


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #26 (permalink)  
Old 04-14-2012, 01:29 AM
Dave Abrahams
Guest
 
Posts: n/a
Default Re: in/out arguments

on Fri Apr 13 2012, Jonathan Thornburg <clcppm-poster-AT-this.is.invalid> wrote:

> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> suggested:
>> Ideally there should
>> be "in", "out" and "in-out" designators as in Ada

>
> James K. Lowden <jklowden@speakeasy.net> wrote:
>> We almost have that now, right?
>>
>> in: value or const reference
>> out: reference
>> in/out: reference
>>
>> The last doesn't deserve distinction. It's rarely used because it's
>> rarely justified.

>
> I have two objections to this last comment. The first is practical:
> I'm willing to take James Lowden's word that in/out arguments are rarely
> used in the code bases he usually sees, but I'm not at all convinced
> that that's true for all C++ code bases.


IMO it's wrong on its face. Every mutating member function uses an
in/out argument. I know, someone will object because "this" is a
pointer. PotAYto potAHto. It could just as easily have been a
reference, and many think it should have been.

I think it probably /is/ rare to have more than 1 in/out argument.
That's a good thing, since mutations are a source of complexity. But
there are notable exceptions, e.g. swap

> For example, in my experience the following sorts of code all make
> frequent use of in/out arguments:


<snip a list>

> There's a pattern here: all of these computations involve in-place updates
> to some data which we don't want to copy
> [possible reasons might include
> * copying would be horribly slow
> * there's not enough memory in the machine to make the copy
> * lots of people hold (and need to keep accessing through)
> pointers to the data]
>
> Admittedly, it's really hard (maybe impossible?) to make such computations
> exception-safe.


Not at all. Always remember (and don't ever forget):

"exception safety" == basic_guarantee
"exception safety" != strong_guarantee

--Dave

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #27 (permalink)  
Old 04-14-2012, 05:35 AM
James K. Lowden
Guest
 
Posts: n/a
Default Re: in/out arguments (was: Re: Why is there no input valueoptimization?)

On Fri, 13 Apr 2012 11:55:16 -0700 (PDT)
Jonathan Thornburg <clcppm-poster@this.is.invalid> wrote:

> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> suggested:
> > Ideally there should
> > be "in", "out" and "in-out" designators as in Ada

>
> James K. Lowden <jklowden@speakeasy.net> wrote:
> > We almost have that now, right?
> >
> > in: value or const reference
> > out: reference
> > in/out: reference
> >
> > The last doesn't deserve distinction. It's rarely used because it's
> > rarely justified.

>
> I have two objections to this last comment. The first is practical:
> I'm willing to take James Lowden's word that in/out arguments are
> rarely used in the code bases he usually sees, but I'm not at all
> convinced that that's true for all C++ code bases.


I welcome the discussion, Jonthan. I hope to learn something from it.

I didn't cite code I usually see. I specifically cited the STL because
as far as I'm concerned that's the canonical example library. And I
didn't say it's never justified, only rarely.

The best-justified case is when the memory in question *can't* be
copied usefully because it's unique. Hardware devices e.g. video
buffers have the property.

I have experience with some of your examples:

> For example, in my experience the following sorts of code all make
> frequent use of in/out arguments:
> * databases (the database is implicitly an in/out argument to lots of
> code)


I've written several database interface libraries. I can't think of one
in/out parameter other than those specified as such by stored
procedures.

If by "the database" you mean the connection handle or similar, those
things don't need to be in the interface.

> * matrix computations like LU decomposition or the singular value
> decomposition (which almost always involve in-place modification of
> matrices)


I wrote a matrix library 15 years ago, and later adopted BLAS. Yes,
there are some tricks needed to make operators convenient to use while
avoiding temporaries, but IIRC very few i/o parameters. Not *none*,
just not that many.

> * sorting algorithms, starting with the classical CS200
> template <typename T> void sort(std::vector<T>& v);


http://www.cplusplus.com/reference/algorithm/sort/

I don't consider iterators to an unpassed container to
be i/o parameters. I think it's notable, actually, that the STL does
not provide sort<vector<T>>.

Dave Abrahams suggests that the this pointer in e.g. list::sort() can
be thought of as an i/o parameter in some sense. Down that road lies a
long computer science debate that I didn't mean to engage.

Please note, my basic point was that i/o parameters are rare enough, on
the evidence, that they don't merit distinction in the language
syntax. I would guess parameters are declared 90% by value, 9% output,
and 1% i/o. That's what I meant by "rarely used".

By "rarely justified", I meant they are to be avoided where possible.
Here's a bad example:

void sqrt( double& value );

I've worked with people who believed passionately that's more
efficient. You don't allocate two or three doubles on the stack; you
just use the one you've got!

I don't have to explain to you why that's wrong; I'm just illustrating
that i/o parameters can be used more often than they are. Any function
whose return type is the same as one of its input parameters is a
candidate. To Just Say No unless it's really needed is the mark of
careful work.

> The fact that a given C++ feature is only used
> rarely in your code, and/or that it's "dangerous" in some way,


..... in that it introduces complexity ...

> doesn't mean that it's not valuable to have in the language


Yes, of course, absolutely.

--jkl


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #28 (permalink)  
Old 04-14-2012, 06:29 PM
Christopher Creutzig
Guest
 
Posts: n/a
Default Re: in/out arguments

On 4/14/12 7:35 AM, James K. Lowden wrote:

> I didn't cite code I usually see. I specifically cited the STL
> because as far as I'm concerned that's the canonical example
> library. And I didn't say it's never justified, only rarely.


I regard the following calls to have in/out parameters and to not be
exotic corner cases of STL:

std::cin << 1;

std::set<int> s;
s.insert(1);

++i;

> Dave Abrahams suggests that the this pointer in e.g. list::sort()
> can be thought of as an i/o parameter in some sense. Down that road
> lies a long computer science debate that I didn't mean to engage.


But both semantically and from an optimization point of view, his
argument makes perfect sense. Pointer/reference is just an
implementation detail when it comes to “this,” and the syntactic sugar
of not having to provide this pointer/reference as an argument to the
function makes code more readable, but does not really change anything
beyond that.

> Please note, my basic point was that i/o parameters are rare enough,
> on the evidence, that they don't merit distinction in the language
> syntax. I would guess parameters are declared 90% by value, 9%
> output, and 1% i/o. That's what I meant by "rarely used".


Since I don't follow the way you are counting, it is not surprising
that my guesstimates are very different from yours. To me, modifying
operations take in/out parameters – the jury is still out on
assignment operators, but I believe those will be found guilty as
well. Not that there's anything wrong with having in/out parameters.

Actually, I'd see “output” parameters as a special case of in/out
parameters (which are denoted by non-const reference in C++) where the
input value is ignored – unless you can show me a valid way to have a
reference parameter which only gets constructed inside the function
called.


Christopher


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #29 (permalink)  
Old 04-15-2012, 06:20 AM
James K. Lowden
Guest
 
Posts: n/a
Default Re: in/out arguments

On Sat, 14 Apr 2012 11:29:31 -0700 (PDT)
Christopher Creutzig <christopher@creutzig.de> wrote:

> > Dave Abrahams suggests that the this pointer in e.g. list::sort()
> > can be thought of as an i/o parameter in some sense. Down that road
> > lies a long computer science debate that I didn't mean to engage.

>
> But both semantically and from an optimization point of view, his
> argument makes perfect sense. Pointer/reference is just an
> implementation detail when it comes to â??this,â?_ and the syntactic
> sugar of not having to provide this pointer/reference as an argument
> to the function makes code more readable, but does not really change
> anything beyond that.


Recall the OP suggested parameters should have syntax denoting their
i/o status (as apparently Ada has). Things like list::sort() and ++i
have no parameters. Would you suggest adding syntax to them?

I'm not saying anything about optimization, which doesn't interest me.
Far more than better compilers, faster execution derives from better
programs, which come from better programmers, who express their logic
to themselves and to other programmers in source code. The language
serves express logic to the humans first, and to the computer only
secondarily. Were that not true, C++ would never have been invented;
we would all be programming in machine code.

Your point IIUC is that things like list::sort looks something like
qsort(3) under the hood. That's not relevant to the question of i/o
parameters per se. My point was and is that C++ syntax makes the use
of i/o parameters unnecessary in most cases.

> > I would guess parameters are declared 90% by value, 9%
> > output, and 1% i/o. That's what I meant by "rarely used".

>
> Since I don't follow the way you are counting, it is not surprising
> that my guesstimates are very different from yours. To me, modifying
> operations take in/out parameters â?? the jury is still out on
> assignment operators,


(Your message arrives at my computer with a header indicating it's
encoded as Windows-1252, but iconv(1) recognizes it as utf-8.)

Well, clearly if we're talking about different things, we're apt to
have different conclusions about them.

I didn't intend to get into the theory because it's not my strength,
but since you raise the subject of assignment, it seems I have to
explain where I'm coming from for you to make sense of what I'm
saying.

As you may know, there's a body of CS research that says assignment and
functions are fundamental, and that side-effects interfere with both
cognition and optimization. I haven't studied it in detail, but I know
in my own experience -- and, I bet, you in yours -- programs are easier
to understand when the data move basically right-to-left. (I hold
operator>> in std::iostreams as an exception that doesn't contradict
the rule of single output. Maybe Stroustrup's disk was located
somewhere to the left of the caps lock key.)

Functions that have two effects -- a result on the left and an output
among the parameters -- are harder to reason about. Certainly to the
extent we embrace centuries of algebraic notation, we're bound to reap
its benefits.

The trend in computer languages is also toward functions and away from
pass-by-reference. In Fortran everything was by reference.
Classically:

SUBROUTINE F ( I )
I = I + 1
END

CALL F(3)

3 is now 4.

By contrast, the functional approach has brought us languages like
Haskell, in which all calls are by value and even variables don't
vary.

Aside: if lazy evaluation were added to C++, could Haskell programs be
written purely in terms of C++ constructors?

I never said i/o parameters can't be used or should be prohibited by
the language. I said they are rarely used and, with the exception of
low-level buffer manipulation, rarely justified. I hope my meaning and
reasoning are now clear.

--jkl


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #30 (permalink)  
Old 04-15-2012, 06:27 AM
Dave Abrahams
Guest
 
Posts: n/a
Default Re: in/out arguments

on Sat Apr 14 2012, "James K. Lowden" <jklowden-AT-speakeasy.net> wrote:

> I don't consider iterators to an unpassed container to
> be i/o parameters. I think it's notable, actually, that the STL does
> not provide sort<vector<T>>.


What in particular do you think is notable about it?

There are actually some very good arguments that the STL should have
provided that interface, and the committee is actively considering
adding it.

> Dave Abrahams suggests that the this pointer in e.g. list::sort() can
> be thought of as an i/o parameter in some sense. Down that road lies a
> long computer science debate that I didn't mean to engage.


I don't see that there's anything much debatable here. Fundamentally
the computation that sorts a list is the same thing whether you spell it
l.sort() (yes, the STL does provide that one) or sort(l). The
underlying machine model against which we program in C++ includes
mutation of state at a fundamental level. If you want to live in a
world where you can dismiss mutation of state as rare, you should be
programming in Haskell. (**)

-Dave

(**) Which isn't to say you're unwelcome here in C++-land, of course :-)

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 09:47 PM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.