Topic: Structs local to functions (was: [LONG] The future of C++)


Author: nde_plume@ziplip.com (Nom De Plume)
Date: 11 Feb 2003 18:59:02 -0500
Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message news:<pSobCwAG9OQ+EwF6@robinton.demon.co.uk>...
> However, I am pretty certain that what makes many advanced ideas
> difficult or easy depends on presentation not on some inherent
> difficulty.

It is obvious, in fact tautological, that ease of learning
depends on quality of instruction, but are you saying that
there are no intrinsically hard ideas in computer science
and computer language acquisition? I respectfully disagree.

I might add along these lines that some things are practically
speaking much harder to teach to people, because they are
not part of the general knowledge that people have already
acquired. Trainee software engineers are undoubtedly familiar
with the concept of function, since they will have spent years
dealing with them in high school, they are very unlikely to
have dealt with something like functors though. Consequently,
functors are generally harder to teach, not just because they
are intrinsically more complex, but also extrinsically, because
they are rarely part of the learner's general knowledge base.

> Actually, it may be easier to teach a genuine unsullied
> novice than one who has been tainted by prior experience from other
> languages.

That is half true. The untainted have the advantage of no
bad habits, but they also have the disadvantage of no
experience. IMHO, usually the latter is more important than
the former, but certainly there are situations where the
reverse is true. The untainted say "that's cool, but what
is it for?", the 'tainted' say "why not just do it this way
instead?" Usually, the latter question is easier to answer
in a deep way.

As I said before, there is a big difference between learning
C++ academically, that is to say, mastering the concepts and
ideas in the language, and learning to become a great C++
software engineer, that is to say learning to put these ideas
into practical application. Language lawyers rarely make good
hackers.)
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 12 Feb 03 18:32:20 GMT
Raw View
In message <b59f4084.0302080745.681e541c@posting.google.com>, Nom De
Plume <nde_plume@ziplip.com> writes
>That is half true. The untainted have the advantage of no
>bad habits, but they also have the disadvantage of no
>experience.

Of course they have experience, it just isn't explicitly computer
programming experience. it is the job of a teacher to help the student
map their existing experience to the terminology of computer
programming.
> IMHO, usually the latter is more important than
>the former, but certainly there are situations where the
>reverse is true. The untainted say "that's cool, but what
>is it for?"

Not in my classroom because I do not teach things unless there is a
manifest use for them. Again, it is the job of the teacher to provide
motives for what is being learnt. Given that the student has chosen to
learn to program, choose tasks that benefit from the technique you want
to teach.

>, the 'tainted' say "why not just do it this way
>instead?" Usually, the latter question is easier to answer
>in a deep way.

Oh, how I wish that were true. It is so easy to get into long
interminable arguments about language design (just look at some of the
threads in this newsgroup such as the one on elision of copy ctors.)

>
>As I said before, there is a big difference between learning
>C++ academically, that is to say, mastering the concepts and
>ideas in the language, and learning to become a great C++
>software engineer, that is to say learning to put these ideas
>into practical application. Language lawyers rarely make good
>hackers.)

That is the difference between learning a natural language and becoming
a novelist, poet, technical writer or journalist. And I think that many
books lack clarity of objective. I neither want the academic approach
nor the 'learn to run races while you learn to crawl' approach.

We also need to distinguish between ground breaking 'research' (Barton &

Nackman, Andrei Alexandrescu etc material) and good fundamentals (Nico
Josuttis, Scott Meyers etc.) You need the latter to become 'a great C++
software engineer' but not the former. And a great software engineer...
would also know when to use a different language so I am dubious about
the 'C++' qualification.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 5 Feb 2003 21:02:50 -0500
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0302031542.5836838b@posting.google.com>...
> Is this based on experience or supposition?

Based half a dozen years of training and mentoring
junior programmers, that is practitioners rather than
formal students.

> I ask because my experience is completely opposite. By the
> time we covered operator overloading, operator() was no
> more difficult than any of the others.

The basic concept is assimilable, the practical application
is where the difficulty arises, specifically, the blurring
of functions and objects, as I mentioned already. Exam
questions are very different from writing real world, working
code.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Daniel James <wastebasket@nospam.aaisp.org>
Date: 06 Feb 03 07:33:58 GMT
Raw View
In article <7f2735a5.0302031534.7df53aaa@posting.google.com>, Allan W
wrote:
> C and C++ are perhaps unique (I don't know about Java) in that
> any expression can be used to form an expression-statement, even
> an expression with no side-effects.
>    void foo() { 2; }
> The statement-expression "2;" is legal, though meaningless.

Algol68 allows this too. In particular typing the boolean expression

  i = 4;

as a typo for the assignment

  i := 4;

compiles without error - though the compiler is apt to throw something
like "Comment: result voided" in your face.

> Surely a "moderately competent" C++ programmer should understand
> operator overloading. operator() is not significantly different
> than operator+.

Yes, agreed, a "moderately competent" programmer who has already learnt
about functors should have no problem at all with the idea that
functors can be overloaded.

I do think that understanding the idea of functors themselves requires
a bit of an intuitive leap when they are first encoutered. At that
stage of learning the language one has become accustomed to the idea
that a class is some sort of data structure that is associated with a
little family of operators and functions that operate implicitly on
objects of the class. I think, though, that grasping that the idea that
defining an operator() allows one to use the name of an object of the
class in the syntax usually associated with a function call requires a
somewhat larger mental step than most other features of the language.
(Perhaps it's just that I had to many preconceived notions about how
the syntax of "C-like" languages worked.)

Cheers,
 Daniel.




      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 06 Feb 03 07:34:13 GMT
Raw View
In article <7f2735a5.0302031542.5836838b@posting.google.com>, Allan W
<allan_w@my-dejanews.com> writes
>I ask because my experience is completely opposite. By the
>time we covered operator overloading, operator() was no
>more difficult than any of the others.

Actually I am not even convinced of the need to have covered other
operator overloading. I am still thinking about this but I suspect that
once you have covered the idea of passing a function pointer (but no
need to actually cover any pointer syntax for these) that functors can
be presented as an alternative way where some 'fixed' data needs to be
included.

However, I am pretty certain that what makes many advanced ideas
difficult or easy depends on presentation not on some inherent
difficulty. Actually, it may be easier to teach a genuine unsullied
novice than one who has been tainted by prior experience from other
languages.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: kanze@gabi-soft.de (James Kanze)
Date: 06 Feb 03 07:34:27 GMT
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0302031534.7df53aaa@posting.google.com>...
> KIM Seungbeom <musiphil@bawi.org> wrote
> > Nom De Plume wrote:

> > > C++ commonly blurs the difference between these two, after all, an
> > > expression is a type of statement.  For example, "p++;" is it an
> > > expression or a statement?  "flag?true_fn():false_fn();" --
> > > expression or statement?  "func_call(a, b, c);" -- expression or
> > > statement? In most languages these would be statements, in C++
> > > they are both statements and expressions.

> > No. C++ is quite clear on this: "p++" is an expression while "p++;"
> > is a statement.

> Quite right. Specifically, "p++;" is an expression-statement.

> C and C++ are perhaps unique (I don't know about Java) in that any
> expression can be used to form an expression-statement, even an
> expression with no side-effects.
>    void foo() { 2; }
> The statement-expression "2;" is legal, though meaningless.

I don't know about "unique".  There's not only Java, AWK, and Perl, but
Lisp, and I imagine most of the other functional languages.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orientie objet/
                    Beratung in objektorientierter Datenverarbeitung

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 4 Feb 2003 15:35:15 -0500
Raw View
KIM Seungbeom <musiphil@bawi.org> wrote
> Nom De Plume wrote:
> >
> > C++ commonly blurs the difference between these two,
> > after all, an expression is a type of statement.
> > For example, "p++;" is it an expression or a statement?
> > "flag?true_fn():false_fn();" -- expression or statement?
> > "func_call(a, b, c);" -- expression or statement? In
> > most languages these would be statements, in C++ they
> > are both statements and expressions.
>
> No. C++ is quite clear on this: "p++" is an expression
> while "p++;" is a statement.

Quite right. Specifically, "p++;" is an expression-statement.

C and C++ are perhaps unique (I don't know about Java) in that
any expression can be used to form an expression-statement, even
an expression with no side-effects.
   void foo() { 2; }
The statement-expression "2;" is legal, though meaningless.

As for functors -- this is a library issue, not a core language
issue. Because of the way templates work, a functor is ANY
expression that can be followed syntactically by parenthesis to
call a function. This is satisfied by function pointers, and by
objects with operator() defined. I don't suspect that neophytes
will have trouble with it. For more experienced C++ programmers,
I disagree with Kim Seungbeom -- or did I miss a smiley? Surely
a "moderately competent" C++ programmer should understand
operator overloading. operator() is not significantly different
than operator+.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: 05 Feb 03 07:55:30 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote
 > operator() is a very hard concept for many learners
 > to grasp, especially when combined with hidden ctors
 > and dtors.

Is this based on experience or supposition? What textbook
were you using? Were these students total novices, or were
they already proficient in some other language? What
language? Did the students have similar problems with other
operators? If so, how did you handle it? If not -- were you
trying to cover functors before you covered operator
overloading? Why?

I ask because my experience is completely opposite. By the
time we covered operator overloading, operator() was no
more difficult than any of the others.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: Charles Calvert <cbcaero@yahoo.com>
Date: 31 Jan 03 02:18:29 GMT
Raw View
On 20 Jan 2003 07:49:49 -0500, nde_plume@ziplip.com (Nom De Plume)
wrote:

>A tuple type could be developed today without
>any extensions to the language.

Indeed.  See boost::tuple for an example.

--
Charles Calvert             |  Software Design/Development
Celtic Wolf, Inc.           |  Project Management
http://www.celticwolf.com/  |  Technical Writing
(703) 580-0210              |  Research

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: KIM Seungbeom <musiphil@bawi.org>
Date: 31 Jan 03 02:18:42 GMT
Raw View
Nom De Plume wrote:
>
> C++ commonly blurs the difference between these two,
> after all, an expression is a type of statement.
> For example, "p++;" is it an expression or a statement?
> "flag?true_fn():false_fn();" -- expression or statement?
> "func_call(a, b, c);" -- expression or statement? In
> most languages these would be statements, in C++ they
> are both statements and expressions.

No. C++ is quite clear on this: "p++" is an expression
while "p++;" is a statement.

--
KIM Seungbeom <musiphil@bawi.org>


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 2 Feb 2003 09:32:25 -0500
Raw View
KIM Seungbeom <musiphil@bawi.org> wrote in message news:<3E395168.7CAA5DA5@bawi.org>...
> No. C++ is quite clear on this: "p++" is an expression
> while "p++;" is a statement.

Although your statement is technically correct, it
entirely misses the point. The discussion is over
the perception of language structures by learners.
Learners generally are not masters of the formal
grammar of a language.

In many programming languages there is a very strong
deliniation between statements and expressions, in
particular, few other languages would have a statement
like "p++;"

The poster I replied to was commenting that using inline
functions as an expression blurred the distinction
between declaration and expression (to the learner,
obviously.) My point was that expressions are already
blurred by the "stmt -> expr ';'" rule, and functors
are even worse in that regard (blurring as they do,
the difference between objects and functions.)

operator() is a very hard concept for many learners
to grasp, especially when combined with hidden ctors
and dtors.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: 28 Jan 03 09:13:54 GMT
Raw View
kanze@gabi-soft.de (James Kanze) wrote in message
news:<d6651fb6.0301230813.5611be57@posting.google.com>...
> allan_w@my-dejanews.com (Allan W) wrote in message
> news:<7f2735a5.0301211453.22535c3e@posting.google.com>...
>
> > Part of my example code showed the local struct having reference
> > members, and initializing them with variables local to the caller.
>
> That's what I currently do.  It makes for a lot of boilerplate code.
> Most of the time I'm doing this, my class only contains one function
> (which overrides a virtual function in the base class).  There's a
> significant difference between having to type:
>
>     struct Op : public Visitor, private __local_context
>     {
>         virtual void visit( T* obj )
>         {
>             //  use local context here...
>         }
>     } ;
>
>     collection.visitAll( Op() ) ;
>
> and the current
>
>     struct Op : public Visitor
>     {
>         Op( Type1& var1, Type2& var2 /* ... */ )
>             :   myVar1( var1 )
>             ,   myVar2( var2 )
>             //  ...
>         {
>         }
>
>         virtual void visit( T* obj )
>         {
>             //  use myVar1 etc. here...
>         }
>
>         Type1& myVar1 ;
>         Type2& myVar2 ;
>         //  ...
>     } ;
>
>     collection.visitAll( Op( var1, var2 /* ... */ ) ;

Were your Op a function object

struct Op
{
  void operator()(T * obj, Type1 & var1, Type2 & var2 /* ... */);
};

you could have used

boost::bind(Op(), ref(var1), ref(var2) /* ... */);

Unfortunately visit() is virtual, so you'll need one more level.

template<class F> class visitor_helper: public Visitor
{
public:

  visitor_helper(F f): f_(f) {}
  virtual void visit(T * obj) { f_(obj); }

private:

  F f_;
};

template<class F> visitor_helper<F> make_visitor(F f)
{
  return visitor_helper<F>(f);
}

collection.visitAll(make_visitor(bind(Op(), ref(var1), ref(var2) /* ...
*/)));

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 30 Jan 2003 09:20:00 -0500
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0301211542.69d6dd@posting.google.com>...
> > By allowing a true lambda definition our code would be
> > much clearer, it would be much easier to explain to neophytes
> > and it would leverage the algorithms in the Standard Library
> > much more powerfully.
>
> I don't think it would be easier to explain to neophytes.
> In fact, I think it would be harder, because it blurs the
> distinction between an expression and a statement.

C++ commonly blurs the difference between these two,
after all, an expression is a type of statement.
For example, "p++;" is it an expression or a statement?
"flag?true_fn():false_fn();" -- expression or statement?
"func_call(a, b, c);" -- expression or statement? In
most languages these would be statements, in C++ they
are both statements and expressions.

This bluring already goes on all over the place in C++,
however, the concept of functors takes it to a different
level, where there is a bluring between a data object
and a statement/expression. For example, "obj();" --
is obj a function, a constructor or an object? As I said
elsewhere, the concept of operator() is very hard for
even moderately competent programmers, never mind neophytes,
to handle.

> Currently we can define a function at namespace/global scope,
> or inline in a class definition. With lambda functions as you
> present them below, you could also define them as a parameter
> to any function. Perhaps even in the middle of an expression?
>
> If your lambda syntax (below) was legal, you could also write this:
>     printf("%p, %p\n",
>            inline getname() { return "Allan" },
>            inline gethorses() { return 2; } );
>
> The results might be undefined (depending if %p handles lambdas)
> but the compiler wouldn't know that. The only difference between
> your call and mine, is that mine is varadic while yours has to
> match the type declared in for_each.)

That is a weakness in the type system deliberately
introduced for C compatiblity. Anonymous functions
do not pretend to solve all problems, however, it
seems relatively obvious to me that the compiler
could readily give a warning for the above saying
"anonymous function defined by not evaluated", using
much the same technique they use for unaccessed
variables.

>   void sum_em(const vector<int> i)
>   {
>     int total = 0;
>     struct local {
>         int &tot;
>         local(int&total) : tot(total) {}
>         void operator()(int a) { tot += a; }
>     };
>     for_each(i.begin(), i.end(), local(total));
>     cout << total << endl;
>   }
>
> These look pretty darn similar to me -- except that, because I've
> defined member functions in classes before, I understand better
> what's going on in the second version. [as opposed to the snipped
                                          example of anonymouse fn]

I imagine it is easier for you. Is it easier for
a learner though? Of course syntax you are familiar
with is easier than new syntax, however the code
above is quite frankly very indirect.

The last parameter to for_each is a very subtle thing:
it means call the ctor on a temporary object and store
the given state, then stop treating me like an object
and pretend I am a function. I'm sure familiarity makes
this easy, (and I might add it is definitely an improvement
on the current state of affairs), but it is certainly
not more readily understandable objectively speaking
than an anonymous function. (Objectively? Yes, because
it is more indirect.)

> > Obviously, I have proposed a slightly modified version
> > of for_each:
> >
> > template<class It, class I, class T>
> > for_each(It b, It e, T& t, void f(I, T))
> > { while(b!=e) f(b++, t); }
> >
> > (Obviously this isn't as flexible as the current for_each
> > but I am not suggesting getting rid of the current for_each
> > but rather adding this as an additional option.)
>
> It also doesn't match the calling code above. Your unnamed
> function takes "const int" as it's first iterator, not
> It::value_type.

Sorry, you are right. I hope the correction is obvious.

> Generally I like what you've proposed -- I'd much rather have these
> changes than no change at all. But it seems to me that it's more than
> we need. It's like using a chainsaw to cut a slice of bread. I like
> the ability to name specific variables to share, rather than trying
> to automatically create a "local context" that gets all locals.
> But I think this can easily be done in a local struct.

I guess that this is the way of the standards process.
You are saying it is a chain saw to cut bread, yet in
another thread somebody accused me of being too
unambitious!

However, I also would prefer your change to nothing.
And your change is so small, and produces significant
enough benefits that it could very well get through
the C++ gatekeepers. Mine, being more extensive, will
surely be rather harder to get through.

> Your big objection to my version is (if I understand correctly) that
> the code is still too far from the call site. Putting this code in
> the function is good, but it really ought to be in the call itself
> to be most useful.

That is part of it, but it is also the level of indirection
that a functor involves that I think is difficult to
assimilate.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 25 Jan 2003 20:17:41 -0500
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0301211453.22535c3e@posting.google.com>...
> kanze@gabi-soft.de (James Kanze) wrote
> > allan_w@my-dejanews.com (Allan W) wrote
> > > I'd like structs declared and defined local to a function.

> > We already have them.

> > > This might be the most obvious syntax to get the equivalent of a
> > > lambda, which a lot of people have asked for under very far.

> > They're not the equivalent of a lambda, since the member functions
> > cannot access local variables.

> Do they need to?

Sometimes.  Sometimes, it's just a matter of syntax; I could just as
easily declare a local instance of the class, with the variables in the
class, and access them through it: e.g. local.i, rather than simply i.
Sometimes, however, the variables must have a longer lifetime than the
instance of the local class; the most obvious case of this is when the
variable is an argument.

> Part of my example code showed the local struct having reference
> members, and initializing them with variables local to the caller.

That's what I currently do.  It makes for a lot of boilerplate code.
Most of the time I'm doing this, my class only contains one function
(which overrides a virtual function in the base class).  There's a
significant difference between having to type:

    struct Op : public Visitor, private __local_context
    {
        virtual void visit( T* obj )
        {
            //  use local context here...
        }
    } ;

    collection.visitAll( Op() ) ;

and the current

    struct Op : public Visitor
    {
        Op( Type1& var1, Type2& var2 /* ... */ )
            :   myVar1( var1 )
            ,   myVar2( var2 )
            //  ...
        {
        }

        virtual void visit( T* obj )
        {
            //  use myVar1 etc. here...
        }

        Type1& myVar1 ;
        Type2& myVar2 ;
        //  ...
    } ;

    collection.visitAll( Op( var1, var2 /* ... */ ) ;

> > My own thoughts in this direction would be to start with an implicit
> > struct (__local_context), implicitly declared to have one variable
> > for each visible variable, whose type is a reference to the type of
> > the visible variable, and which is implicitly initialized to refer
> > to the visible variable.

> Would this structure be any easier to use, or any more efficient, than
> having reference members in the local struct?

Easier to use, see above.  More efficient, definitly, because what I
have just written defines the semantics, not the actual implementation.
I would expect a compiler to implement it with only a pointer to the
local stack frame, rather than a lot of individual references.  (The
compiler knows the exact layout of the local stack frame in the class,
so can generate the appropriate code.)

> > There is currently a restriction that the types used to instantiate
> > a template must have external linkage, so you cannot use local types
> > with templates.

> Right, that's what I should have said in the first place -- I'd like
> to be able to use local types with templates, to make the example code
> that I posted legal.

That's a separate issue.  I was doing this long before templates
arrived, and even today, most of the time, I'm using derivation -- my
visitAll functions aren't templates (and are often virtual, the visitor
being used to effectuate a sort of multiple dispatch).

I see no reason not to allow local classes to be used to instantiate
templates as well.  At least, not until some implementor tells me that
it will cause them problems (which I doubt).  But it won't help in the
above scenario.

You can add a number of convenience features to the above: my idea of
lambda functions would be an implicitly defined class along the lines
of:

    struct Lambda : private __local_context
    {
        returnType operator()( ... ) { ... }
    } ;

for example.  But such convenience features aren't necessary for the
basic idea to be useful.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: 27 Jan 03 05:22:43 GMT
Raw View
kanze@gabi-soft.de (James Kanze) wrote (abridged):
> > Part of my example code showed the local struct having reference
> > members, and initializing them with variables local to the caller.
>
> That's what I currently do.  It makes for a lot of boilerplate code.

How much of this can be dealt with using templates? If it cannot be done
now, would it be better, more general, to extend the language until it can
be done?

    template <typename T>
    class Local {
        T *ref_;
    protected:
        Local() : ref_(0) {}
        T &ref() { assert(ref_); return *ref_; }
        void set_ref( T &ref ) { ref_ = &ref; }
    };

    void demo( int *first, int *last ) {
        struct Functor : Local<int> {
            void operator()( int i ) {
                ref() += i;
            }
        } functor;
        int sum = 0;
        functor.set_ref( sum );
        for_each( first, last, functor );
        return sum;
    }

This would be better if we could "inherit" constructors.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: "Anders J. Munch" <andersjm@dancontrol.dk>
Date: 24 Jan 03 17:05:10 GMT
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote:
> > By allowing a true lambda definition our code would be
> > much clearer, it would be much easier to explain to neophytes
> > and it would leverage the algorithms in the Standard Library
> > much more powerfully.
>
> I don't think it would be easier to explain to neophytes.
> In fact, I think it would be harder, because it blurs the
> distinction between an expression and a statement.

Quite. It is worth it?

Perhaps we should separate the two issues:
1) Local functions with access to local names.
2) Anonymous function notation.

A good concrete syntax for local named functions is trivial: just
allow full function definitions wherever declarations are allowed
today.  I think this is what gcc does.  Let's start with that.  When
we have the semantics of local functions down, it's soon enough to
start tinkering with short inline notations for it.

If we need those at all; it doesn't seem like a big win to me.  If we
have to write the type declaration out in full every time, it isn't
going to be short and sweet anyway.  I don't see
  std::sort(x.begin(), x.end(),
    inline bool (elementtype& lhs, elementtype& rhs)
 { return lhs.b < rhs.b; });
having gained anything over:
   bool compare_by_b(elementtype& lhs, elementtype& rhs)
  { return lhs.b < rhs.b; }
   std::sort(x.begin, x.end(), compare_by_b);

Perhaps anonymous functions need to be coupled with some measure of
type inference?
    // sweet, but has gazillions of issues:
    std::sort(x.begin(), x.end(), (lhs,rhs) => (lhs.b < rhs.b));

Or perhaps that is better left to C1x.

--
Anders Munch. Software Engineer, Dancontrol A/S, Haderslev, Denmark
Still confused but at a higher level.



      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 23 Jan 03 07:20:26 GMT
Raw View
nde_plume@ziplip.com (Nom De Plume) wrote
> allan_w@my-dejanews.com (Allan W) wrote
> > I'd like structs declared and defined local to a function.
> >
> > This might be the most obvious syntax to get the equivalent of a
lambda,
> > which a lot of people have asked for under very far.
>
> Of course local structs are legal now in C++, but, AFAIK
> it is not possible to use them to instantiate templates.
>
> For example:
>
> void f(vector<int>& a)
> {
>   struct S {operator()(int&i) { i++;};} s;
>   for_each(a.begin(), a.end(), s);
> }
>
> is not allowed. As someone else pointed out, if you use a
> static function in S you can pass in a pointer to for_each
> and get the same effect.
>
> However, this seems to me to miss the whole point. It
> is true that bringing the function definition into local
> scope is an improvement on having lots of little one time
> use functions and functors spread throughout your code,
> but it is still not declaring the function where you actually
> want it. It is obscure, especially when using some subtle
> point like using a static function.

Doesn't seem so obscure to me. I think using local functions allows
us to "pass code" to a function without making extensive language
changes.

> By allowing a true lambda definition our code would be
> much clearer, it would be much easier to explain to neophytes
> and it would leverage the algorithms in the Standard Library
> much more powerfully.

I don't think it would be easier to explain to neophytes.
In fact, I think it would be harder, because it blurs the
distinction between an expression and a statement.

Currently we can define a function at namespace/global scope,
or inline in a class definition. With lambda functions as you
present them below, you could also define them as a parameter
to any function. Perhaps even in the middle of an expression?

If your lambda syntax (below) was legal, you could also write this:
    printf("%p, %p\n",
           inline getname() { return "Allan" },
           inline gethorses() { return 2; } );

The results might be undefined (depending if %p handles lambdas)
but the compiler wouldn't know that. The only difference between
your call and mine, is that mine is varadic while yours has to
match the type declared in for_each.)

> The question I have wrestled with for a few days is how to
> make the data you need available in the lambda function.

That's another argument for local structs; using references, you
can simply leave this up to the programmer.

> Dealing with local variables first, there are various
> extensions to the syntax that would make this feasible,
> but in retrospect, it seems to me that the easiest approach
> is to use the technique that has been used in software
> for years:
>
> void sum_em(const vector<int> i)
> {
>   int total = 0;
>   for_each(i.begin(), i.end(), total,
>            inline void (const int i, int& total)
>            {
>               total += i;
>            });
>   cout << total << endl;
> }

  void sum_em(const vector<int> i)
  {
    int total = 0;
    struct local {
        int &tot;
        local(int&total) : tot(total) {}
        void operator()(int a) { tot += a; }
    };
    for_each(i.begin(), i.end(), local(total));
    cout << total << endl;
  }

These look pretty darn similar to me -- except that, because I've
defined member functions in classes before, I understand better
what's going on in the second version.

> Obviously, I have proposed a slightly modified version
> of for_each:
>
> template<class It, class I, class T>
> for_each(It b, It e, T& t, void f(I, T))
> { while(b!=e) f(b++, t); }
>
> (Obviously this isn't as flexible as the current for_each
> but I am not suggesting getting rid of the current for_each
> but rather adding this as an additional option.)

It also doesn't match the calling code above. Your unnamed
function takes "const int" as it's first iterator, not
It::value_type.

Generally I like what you've proposed -- I'd much rather have these
changes than no change at all. But it seems to me that it's more than
we need. It's like using a chainsaw to cut a slice of bread. I like
the ability to name specific variables to share, rather than trying
to automatically create a "local context" that gets all locals.
But I think this can easily be done in a local struct.

Your big objection to my version is (if I understand correctly) that
the code is still too far from the call site. Putting this code in
the function is good, but it really ought to be in the call itself
to be most useful.

Maybe that makes sense, but you can take it too far. After all, you
declare function parameters after the function name, not at the point
of first use. You declare base classes after the class name, not at
the point where you make direct use of that class. And so on.

By putting the code into a local class, we move it very, very close
to the point of call... which ought to satisfy the general need for
lambdas. At the same time we avoid most of the complicated issues
that make lambdas problematic, such as how to address local
variables, and so on.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 23 Jan 03 07:21:42 GMT
Raw View
> allan_w@my-dejanews.com (Allan W) writes:
> > I'd like structs declared and defined local to a function.

Anthony Williams <anthony.williamsNOSPAM@anthonyw.cjb.net> wrote
> Which you have already. From reading the rest of your post, it is apparent
> that what you want is for these local classes to have external linkage, so
> they can be used as template arguments. This requires a language change,
> along the lines of my proposal at
>    http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1353.html

Yes, that's exactly what I want.

> I will be submitting a revised version in time for the next
> Standard Committee meeting in April.

In your conversations with others in the Standards Committee, has
this concept generally been seen in a good light? (I really want to
ask your prediction about whether this will be part of the next standard
or not, but I know that it's too early to tell... also, you wouldn't
bother proposing it if you didn't think it could make it in...)

Does it help to have support from people not on the Committee, but
who frequent this newsgroup? If so, you can count me in the "yes"
category.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: allan_w@my-dejanews.com (Allan W)
Date: 22 Jan 03 05:34:22 GMT
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> allan_w@my-dejanews.com (Allan W) wrote
> > I'd like structs declared and defined local to a function.
>
> We already have them.
>
> > This might be the most obvious syntax to get the equivalent of a
> > lambda, which a lot of people have asked for under very far.
>
> They're not the equivalent of a lambda, since the member functions
> cannot access local variables.

Do they need to? Part of my example code showed the local struct
having reference members, and initializing them with variables local
to the caller.

> My own thoughts in this direction would
> be to start with an implicit struct (__local_context), implicitly
> declared to have one variable for each visible variable, whose type is a
> reference to the type of the visible variable, and which is implicitly
> initialized to refer to the visible variable.

Would this structure be any easier to use, or any more efficient, than
having reference members in the local struct?

> There is currently a restriction that the types used to instantiate a
> template must have external linkage, so you cannot use local types with
> templates.

Right, that's what I should have said in the first place -- I'd like
to be able to use local types with templates, to make the example
code that I posted legal.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: nde_plume@ziplip.com (Nom De Plume)
Date: 20 Jan 2003 07:49:49 -0500
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0301141417.735869da@posting.google.com>...
> I'd like structs declared and defined local to a function.
>
> This might be the most obvious syntax to get the equivalent of a lambda,
> which a lot of people have asked for under very far.

Of course local structs are legal now in C++, but, AFAIK
it is not possible to use them to instantiate templates.

For example:

void f(vector<int>& a)
{
  struct S {operator()(int&i) { i++;};} s;
  for_each(a.begin(), a.end(), s);
}

is not allowed. As someone else pointed out, if you use a
static function in S you can pass in a pointer to for_each
and get the same effect.

However, this seems to me to miss the whole point. It
is true that bringing the function definition into local
scope is an improvement on having lots of little one time
use functions and functors spread throughout your code,
but it is still not declaring the function where you actually
want it. It is obscure, especially when using some subtle
point like using a static function.

By allowing a true lambda definition our code would be
much clearer, it would be much easier to explain to neophytes
and it would leverage the algorithms in the Standard Library
much more powerfully.

The question I have wrestled with for a few days is how to
make the data you need available in the lambda function.
It seems to me that, outside of global data which the
function can access anyway, that you need access to two
categories of data: local variables and class member
functions and variables.

Dealing with local variables first, there are various
extensions to the syntax that would make this feasible,
but in retrospect, it seems to me that the easiest approach
is to use the technique that has been used in software
for years:

void sum_em(const vector<int> i)
{
  int total = 0;
  for_each(i.begin(), i.end(), total,
           inline void (const int i, int& total)
           {
              total += i;
           });
  cout << total << endl;
}

Obviously, I have proposed a slightly modified version
of for_each:

template<class It, class I, class T>
for_each(It b, It e, T& t, void f(I, T))
{ while(b!=e) f(b++, t); }

(Obviously this isn't as flexible as the current for_each
but I am not suggesting getting rid of the current for_each
but rather adding this as an additional option.)

Generally speaking it strikes me that only one variable
is usually needed from the local scope, and so this
simple approach covers a large fraction of our needs.

What about if you need more variables from the local
scope? Clearly the simple solution is to use some sort
of composite variable to pass these in. The syntax for
this can be made rather simple by using a simple tuple
type:

void sum_squares(vector<int> i)
{
  // Calculate the sum and the sum of squares
  int total = 0, total_squares = 0;

  for_each(i.begin(), i.end(), tuple(total, total_squares),
           inline void(int i, tuple<int, int> t)
           {
              t.first += i;
              t.second += i*i;
           });
  cout << total << ", " << total_squares << endl;
}

A tuple type could be developed today without
any extensions to the language. Of course it would be
nice if the member variables of the tuple could be
renamed to correspond to the local variable names,
but that would require a bunch of new syntax. Along
these lines I like the idea proposed by someone else
here that there be some mechanism to make a structure
containing refs to all local variables, which you can
pass in, but it seems unlikely that such a thing would
be acceptable in the standard.

What about class access? I have proposed the following
syntax:

class Item {...};

class ItemsList { /* ...*/
  private:
    list<Item> lst_;
    double total_price_;

    void processItems();
    void processItem(Item& i);
};

// processItems calls processItem on each item
// to get it up to date, then sums the prices
// of each item to update the member variable
// total_price_
void ItemsList::processItems()
{
  total_price = 0;
  for_each(lst_.begin(), lst_.end(),
           class inline void(Item& i)
           {
              processItem(i);
              total_price += i.price();
           });
}

Here I have used the syntax "class inline" meaning define
this as an anonymous private member function of the class
of the enclosing function. This allows me to do two things
in my lambda function: access the private member function
processItem, and access the private member variable
total_price_. (Note also, I have used the current form of
for_each here because I don't need to pass in additional
data, since it is all contained in the class.)

So then, I'd propose two extensions, an expression can be
of the syntax:

unary-expression:
   class(opt) inline dname(opt)
              { argument-declaration-list } fct-body

Semantically, this means, without the class designator,
declare an anonymous function, with the given arguments
and body, and resolve the unary-expression to be a pointer
to that function. With the class designator, it means declare
an anonymous private member function in the class of the
containing function, and resolve the unary-expression to be
a pointer to that member function. (Obviously, the latter is
illegal when used in a non member function.)

Just for fun, I have also allowed the "anonymous" function
to have a name, since it might be useful to use such to
document the purpose of the function. No semantics attach
to the name.

And of course, there is the expectation in both cases that
the compiler will inline the function, but that is more of
a pragmatic concern, the semantics are as above.

Secondly, I'd propose an extension to the algorithm functions
in the standard library to include an optional argument that
can be passed into the functor, the same value for every
call. (Example of for_each given above.)

One final point, is that by making this part of the general
expression syntax you have raised functions pretty close
to first class objects. One can imagine some cool uses for
such an idea, for example:

double(*)(Item& i)
calcPostage(Country country)
{
// Return a function that calculates the postage
// on a given item going to the given country.
  switch(country)
  {
  case USA:  return inline double (Item& i)
                           { return i.weight * 0.50; };
  case UK:   return inline double (Item& i)
                           { return i.weight * 0.75; };
  case Australia:
             return inline double (Item& i)
                           { return i.weight * 1.25; };
  // etc
  }
}

But maybe that is going too far :-)
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tom_usenet@hotmail.com (tom_usenet)
Date: 17 Jan 03 03:54:36 GMT
Raw View
On 16 Jan 2003 16:57:53 GMT, allan_w@my-dejanews.com (Allan W) wrote:

>
>I'd like structs declared and defined local to a function.
>
>This might be the most obvious syntax to get the equivalent of a lambda,
>which a lot of people have asked for under very far. But it doesn't
>stretch the syntax very far (no new keywords, either). All functions are
>inline, which means they shouldn't be very big -- and when used with
>inline functions (like the STL's for_each and sort), the whole thing can
>be as efficient as if it was written out the long way.
>
>nde_plume@ziplip.com (Nom De Plume) wrote
>> struct s {int a; string b;};
>>
>> void sort_em(vector<s>& data)
>> {
>>   sort(data.begin(), data.end(),
>>        inline bool(const s& lhs, const s& rhs)
>>        {
>>            return lhs.b < rhs.b;
>>        });
>> }
>
>void sort_em(vector<s>&data) {
>    // comp is an STL-style functor, but it's local to sort_em
>    struct {
>        bool operator()(const s&lhs, const s&rhs) { return lhs.b <
>rhs.b; }
>    } comp;
>    sort(data.begin(), data.end(), comp);
>}

This can already be done without changing the language:

void sort_em(vector<s>&data) {
    // comp is an STL-style functor, but it's local to sort_em
    struct comp {
     static bool func()(const s&lhs, const s&rhs)
 { return lhs.b < rhs.b; }
    };
    sort(data.begin(), data.end(), &comp::func);
}

There is probably a loss of efficiency though of course, due to using
a function pointer.

Now, the question is, why can't we use non-extern names as template
parameters? I think the reason is due to how template instantiation
mechanism works. So the next question becomes, why can't local structs
have external linkage? The answer is that someone has suggested that
they should:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1353.html

Tom

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]




Author: belvis@pacbell.net (Bob Bell)
Date: 17 Jan 2003 06:56:45 -0500
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0301141417.735869da@posting.google.com>...
> I'd like structs declared and defined local to a function.
>
> This might be the most obvious syntax to get the equivalent of a lambda,
> which a lot of people have asked for under very far. But it doesn't
> stretch the syntax very far (no new keywords, either). All functions are
> inline, which means they shouldn't be very big -- and when used with
> inline functions (like the STL's for_each and sort), the whole thing can
> be as efficient as if it was written out the long way.

Can't you already do this?

Bob Bell
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: 18 Jan 2003 05:38:32 -0500
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0301141417.735869da@posting.google.com>...
> I'd like structs declared and defined local to a function.

We already have them.

> This might be the most obvious syntax to get the equivalent of a
> lambda, which a lot of people have asked for under very far.

They're not the equivalent of a lambda, since the member functions
cannot access local variables.  My own thoughts in this direction would
be to start with an implicit struct (__local_context), implicitly
declared to have one variable for each visible variable, whose type is a
reference to the type of the visible variable, and which is implicitly
initialized to refer to the visible variable.

Just having this, and using it as a base class, would give all of the
necessary functionality.  Additional features would simply make some of
the more common uses easier.

> But it doesn't stretch the syntax very far (no new keywords,
> either). All functions are inline, which means they shouldn't be very
> big -- and when used with inline functions (like the STL's for_each
> and sort), the whole thing can be as efficient as if it was written
> out the long way.

The restriction that the functions must be inline is also present today.

There is currently a restriction that the types used to instantiate a
template must have external linkage, so you cannot use local types with
templates.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David B. Held" <dheld@codelogicconsulting.com>
Date: 18 Jan 2003 05:42:01 -0500
Raw View
"tom_usenet" <tom_usenet@hotmail.com> wrote in message
news:3e26eb42.108007546@news.easynet.co.uk...
> [...]
> void sort_em(vector<s>&data) {
>     // comp is an STL-style functor, but it's local to sort_em
>     struct comp {
>     static bool func()(const s&lhs, const s&rhs)
> { return lhs.b < rhs.b; }
>     };
>     sort(data.begin(), data.end(), &comp::func);
> }
> [...]

How does sort call comp::func?  What is the result of *&comp::func?
Are you sure it's a callable entity?

Dave
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Anthony Williams <anthony.williamsNOSPAM@anthonyw.cjb.net>
Date: 18 Jan 2003 05:42:26 -0500
Raw View
allan_w@my-dejanews.com (Allan W) writes:

> I'd like structs declared and defined local to a function.

Which you have already. From reading the rest of your post, it is apparent
that what you want is for these local classes to have external linkage, so
they can be used as template arguments. This requires a language change, along
the lines of my proposal at
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1353.html ; I will be
submitting a revised version in time for the next Standard Committee meeting
in April.

Anthony
--
Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Carlos Moreno <moreno_at_mochima_dot_com@xx.xxx>
Date: 18 Jan 2003 15:52:01 -0500
Raw View
tom_usenet wrote:
>>
>>void sort_em(vector<s>&data) {
>>   // comp is an STL-style functor, but it's local to sort_em
>>   struct {
>>       bool operator()(const s&lhs, const s&rhs) { return lhs.b <
>>rhs.b; }
>>   } comp;
>>   sort(data.begin(), data.end(), comp);
>>}
>
> This can already be done without changing the language:
>
> void sort_em(vector<s>&data) {
>     // comp is an STL-style functor, but it's local to sort_em
>     struct comp {
>      static bool func()(const s&lhs, const s&rhs)
>  { return lhs.b < rhs.b; }
>     };
>     sort(data.begin(), data.end(), &comp::func);

Funny how you state that "This [what the previous poster did]
can already be done"...  And then you do something *completely*
different.

You *can not* do what the previous poster wanted to do (use
a local struct as an STL functor).  You don't want to use a
pointer to function, or a pointer to a static member function,
since a functor with an inlined operator() is more efficient,
and in some cases is necessary -- say, something like:

count_if (strings.begin(), strings.end(), longer_than(30));

(to count how many strings have length > 30)


Carlos
--
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: 16 Jan 2003 16:57:53 GMT
Raw View
I'd like structs declared and defined local to a function.

This might be the most obvious syntax to get the equivalent of a lambda,
which a lot of people have asked for under very far. But it doesn't
stretch the syntax very far (no new keywords, either). All functions are
inline, which means they shouldn't be very big -- and when used with
inline functions (like the STL's for_each and sort), the whole thing can
be as efficient as if it was written out the long way.

nde_plume@ziplip.com (Nom De Plume) wrote
> struct s {int a; string b;};
>
> void sort_em(vector<s>& data)
> {
>   sort(data.begin(), data.end(),
>        inline bool(const s& lhs, const s& rhs)
>        {
>            return lhs.b < rhs.b;
>        });
> }

void sort_em(vector<s>&data) {
    // comp is an STL-style functor, but it's local to sort_em
    struct {
        bool operator()(const s&lhs, const s&rhs) { return lhs.b <
rhs.b; }
    } comp;
    sort(data.begin(), data.end(), comp);
}

> Or
>
> // Note this defines a functor with the "inline" function
> // which on construction takes a reference to total, based
> // on the using declaration in the anonymous function.
> int sum_em(const vector<int> data)
> {
>   int total = 0;
>   for_each(data.begin(), data.end(),
>            inline void(const int val)
>            {

                // I think you meant "total" instead of "a" in next 2
lines
>               using a; // Note no scope meaning enclosing function
>               a += v;
>            });
     return total; // Probably meant this too
> }

int sort_em(vector<int> data) {
    int total=0;
    // comp is an STL-style functor, but it's local to sort_em
    // The total is a reference to a non-local int; therefore,
    // the comp object may be copied as often as you like,
    // with no ill effects.
    struct comp {
        int&tot;
        comp(int&t) : tot(t) {}
        bool operator()(int val) { tot += val; }
    };
    for_each(data.begin(), data.end(), comp(total));
    return total;
}

> Finally, consider:
>
> class A
> {
>  ...
> private:
>   void processValue(int v);
>   void processList();
>   std::list<int> dataList;
> }
>
> // By using "class inline" this function is
> // declared as an anonymous private member
> // function of the class of the enclosing
> // member function. Giving access to processValue
> void A::processList()
> {
>   // call processValue with every item on list
>   for_each(dataList.begin(), dataList.end(),
>            class inline void(const int v)
>            {
>                processValue(v);
>            });
> }

  void A::processList() {
      // proc is an STL-style functor.
      // It is NOT a member of class A, so it needs a
      // pointer to member function -- and an element of type A.
      struct proc {
          void A&that;
          void A::(*pmf)(int);
          proc(A&a, A::(*p)(int)) : that(a), pmf(p) {}
          void operator()(int v) { that.*pmf(v); }
      };
      for_each(dataList.begin(), dataList.end(),
proc(*this,A::processValue));
    }

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]