Assignment library: review

Hi, This is formal review for the assignment library. Library present partial solution for frequent problem of collection initialization. In spite of several implementation issues I incline to accept this submission subject to resolution of Design Issue 1. Design --------------------------------------------- 1. Global operator+= and operator<< I believe defining global operator+= and operator<< is unacceptable (and it is global, cause to be used they require to be brought into space by using statement). I propose to remove it and introduce instead operator+= and implementation in headers dedicated to specific stl containers like this: template <class T, class Alloc> inline insert_assigner<std::list<T,Alloc> > operator+=( std::list<T,Alloc>& c, const typename std::list<T,Alloc>::value_type& v ) { return insert_assigner<std::list<T,Alloc> >( c, v ); } and operator << in appropriate extension headers. 2. Forwarding problem This library is affected by forwarding problem. I do not know how important it is, but may be we should use by-value scheme used by boost::bind? 3. Library doesn't allow to create const collections. Well, I am not sure whether or not it's doable but currently it's not supported Implementation --------------------------------------------- 1. insert_assigner( C& c, const value_type& v ) as well as fixed_size_assigner( const iterator& begin, const iterator& end, const value_type& v ) are unnecessary 2. Should we use Boost::pp to implement insert_assigner, fixed_size_assigner e.t.c. and have configurable limit? 3. Obviously code needs to be refactored into smaller pieces. One header per stl container. Also by default it shouldn't include boost related extensions 4. ~fixed_size_assigner This method may throw an exception. Does it always safe to rely on uncaught_exception call? Could we move this somehow out of destructor? 5. No function template ordering handling Why not use usual trick with extra long parameter? 6. Why not use tuple_insert_assigner for matrix assignment? Wouldn't be safer? 7. Promised support for MSVC 6.0 doesn't seems to work Code --------------------------------------------- 1. Why insert_assigner needs to include <boost/call_traits.hpp> 2. What is make.hpp,template.hpp? 3. I would name insert as append, cause it actually does not support inside the collection and this is after all is assignment library 4. Code comments needs to be removed Tests --------------------------------------------- 1. Tests doesn't seem to perform runtime correctness checks in most cases or rely on assert for checks. It would be preferable to use more graceful error checks. Good job, Gennadiy.

Hi Gennadiy, Thanks for your review.
2. Forwarding problem This library is affected by forwarding problem. I do not know how important it is, but may be we should use by-value scheme used by boost::bind?
won't boost::ref <> "solve" this. (don't bind use &?)
3. Library doesn't allow to create const collections. Well, I am not sure whether or not it's doable but currently it's not supported
It has already been suggested to support const vector<int> v = init( v )(1)(2).
1. insert_assigner( C& c, const value_type& v ) (a) as well as fixed_size_assigner( const iterator& begin, const iterator& end, const value_type& v ) are unnecessary (b)
(a) is used with operator+=() (b) is used with operator<<(). If this goes away, it will sill eb used in eg assign_all( array ) = 1,2,3;
2. Should we use Boost::pp to implement insert_assigner, fixed_size_assigner e.t.c. and have configurable limit?
3. Obviously code needs to be refactored into smaller pieces. One header
Some have wanted this. I have no problems with it besides I can't see what its good for. Having a function/constructor with more than X arguments (x small) is hardly good practice. per
stl container. Also by default it shouldn't include boost related extensions
ok.
4. ~fixed_size_assigner This method may throw an exception. Does it always safe to rely on uncaught_exception call?
No, it is not always safe, but the unsafe stuff happens if you use it in a destructor; not very likely. Sutter has an article about it.
Could we move this somehow out of destructor?
Yes. I would prefer to default initialize the remaining elements. It do put that additional requirement on the suported types, but not a big thing IMO.
5. No function template ordering handling Why not use usual trick with extra long parameter?
Sure. What's the trick and what's the issue?
6. Why not use tuple_insert_assigner for matrix assignment? Wouldn't be safer?
No. A matrix is usually a fixed sized container, eg a 4-by-4 matrix. Thus we can make bounds checking. tuple_insert_assigner is used for forwarding to functions that take a "tuple" of arguments. Just plain forwarding.
7. Promised support for MSVC 6.0 doesn't seems to work
It's been a while since I did the test. I won't promise vc6 support with the new proposed changes, but I will try.
1. Why insert_assigner needs to include <boost/call_traits.hpp>
It don't. Thanks.
2. What is make.hpp,template.hpp?
just rubbish.
3. I would name insert as append, cause it actually does not support inside the collection and this is after all is assignment library
good idea.
1. Tests doesn't seem to perform runtime correctness checks in most cases or rely on assert for checks. It would be preferable to use more graceful error checks.
Yes. Tom wanted real test too.
Good job,
thanks. br Thorsten

So what about 1?
2. Forwarding problem This library is affected by forwarding problem. I do not know how important it is, but may be we should use by-value scheme used by boost::bind?
won't boost::ref <> "solve" this. (don't bind use &?)
No and no.
3. Library doesn't allow to create const collections. Well, I am not sure whether or not it's doable but currently it's not supported
It has already been suggested to support
const vector<int> v = init( v )(1)(2).
How you plan to implement this? init( v ) wouldn't be able to modify v since it is declared const.
1. insert_assigner( C& c, const value_type& v ) (a) as well as fixed_size_assigner( const iterator& begin, const iterator& end, const value_type& v ) are unnecessary (b)
(a) is used with operator+=()
You don't need it template< typename C > inline insert_assigner<C> operator+=( C& c, const typename C::value_type& v ) { return insert_assigner<C>( c ), v; } The same idea with second guy.
(b) is used with operator<<(). If this goes away, it will sill eb used in eg
assign_all( array ) = 1,2,3;
Why?
2. Should we use Boost::pp to implement insert_assigner, fixed_size_assigner e.t.c. and have configurable limit?
Some have wanted this. I have no problems with it besides I can't see what its good for. Having a function/constructor with more than X arguments (x small) is hardly good practice.
Why 6 then? Why not 4?
4. ~fixed_size_assigner This method may throw an exception. Does it always safe to rely on uncaught_exception call?
No, it is not always safe, but the unsafe stuff happens if you use it in a destructor; not very likely. Sutter has an article about it.
Where?
5. No function template ordering handling Why not use usual trick with extra long parameter?
Sure. What's the trick and what's the issue?
template< typename C, typename V > inline void make_insertion( C& c, const V& v, long ) { c.insert( c.end(), v ); } ... void insert_( const value_type& v ) { make_insertion( c_, v, 0 ); // 0 is of type int } Now you could use generic version even for compilers that does not support partial ordering and you could remove all repetition from stl.hpp Gennadiy.

"Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote in message news:c59i86$39d$1@sea.gmane.org...
So what about 1?
There seem to be more people who want this, but I leave it to Tom to summarize required changes.
2. Forwarding problem This library is affected by forwarding problem. I do not know how important it is, but may be we should use by-value scheme used by boost::bind?
won't boost::ref <> "solve" this. (don't bind use &?)
No and no.
(a) My comments about boost::bind comes from http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm But bind's reference docs seems to use by-value. (b) I've attached a small example that demonstrates why we should not use by-value: 1. it passes a reference to a temporary 2. it removes constness (and do (1)) const& is good because 1. it disallows buggy code to compile 2. references can be passes with boost:ref You must know something I have overlooked :-) At the latest wg21 meeting, Dietmar was worried about function<> using by by-value. So far I agree.
3. Library doesn't allow to create const collections. Well, I am not sure whether or not it's doable but currently it's not supported
It has already been suggested to support
const vector<int> v = init( v )(1)(2).
How you plan to implement this? init( v ) wouldn't be able to modify v since it is declared const.
Yes, it's simple. Just stuff the values into a temporary and provide a conversion operator. I actually plan to support two versions 1. without container argument (slightly slower, convinient): const vector<int> c = make_list(1)(1)(2)(3); 2. with container argument or properly specialized (slightly faster, less convinient) const vector<int> c = list( c )(1)(1)(2)(3); // or const vector<int> c = make_vector(1)(1)(2)(3); For stl, it could make sence to add make_vector() etc. This kind of anonymous list can also be used with container algorithms: copy( list(1)(2)(3), // bind to a const& ostream_iterator<int>( cout ) ); Of course, this will have to be asssesed in a post-review version provided the library is accepted.
(a) is used with operator+=()
You don't need it
template< typename C > inline insert_assigner<C> operator+=( C& c, const typename C::value_type& v ) { return insert_assigner<C>( c ), v; }
The same idea with second guy.
true.
(b) is used with operator<<(). If this goes away, it will sill eb used in eg
assign_all( array ) = 1,2,3;
Why?
no idea anymore :-)
2. Should we use Boost::pp to implement insert_assigner, fixed_size_assigner e.t.c. and have configurable limit?
Some have wanted this. I have no problems with it besides I can't see what its good for. Having a function/constructor with more than X arguments (x small) is hardly good practice.
Why 6 then? Why not 4?
I agree four is even better.
4. ~fixed_size_assigner This method may throw an exception. Does it always safe to rely on uncaught_exception call?
No, it is not always safe, but the unsafe stuff happens if you use it in a destructor; not very likely. Sutter has an article about it.
Where?
http://www.gotw.ca/gotw/047.htm
5. No function template ordering handling Why not use usual trick with extra long parameter?
Sure. What's the trick and what's the issue?
template< typename C, typename V > inline void make_insertion( C& c, const V& v, long ) { c.insert( c.end(), v ); }
...
void insert_( const value_type& v ) { make_insertion( c_, v, 0 ); // 0 is of type int }
Now you could use generic version even for compilers that does not support partial ordering and you could remove all repetition from stl.hpp
neat. I'll use it when cleaning up the code. Thanks. br Thorsten begin 666 ref.cpp M#0HC:6YC;'5D92 \8F]O<W0O<F5F+FAP<#X-"B-I;F-L=61E(#QI;W-T<F5A M;3X-"@T*=7-I;F<@;F%M97-P86-E('-T9#L-"G5S:6YG(&YA;65S<&%C92!B M;V]S=#L-"@T*=F]I9"!F;V\H(&EN="8@:2 I( T*>PT*(" @(&-O=70@/#P@ M)FD@/#P@(B B.PT*?0T*#0IT96UP;&%T93P@8VQA<W,@5" ^#0IV;VED(&9O M<G=A<F0H(%0@=" I#0I[#0H@(" @9F]O*"!T("D[#0I]#0H-"G1E;7!L871E M/"!C;&%S<R!4(#X-"G9O:60@<')O<&5R7V9O<G=A<F0H(&-O;G-T(%0F('0@ M*0T*>PT*(" @(&9O;R@@=" I.PT*?0T*#0II;G0@;6%I;B@I#0I[#0H@(" @ M:6YT(&D@/2 Q.PT*(" @(&-O;G-T(&EN="!C:2 ](#$[#0H@(" @8V]U=" \ M/" F:2 \/" B("([#0H@(" @9F]R=V%R9"@@:2 I.R @+R\@;V]P<PT*(" @ M(&9O<G=A<F0H(&D@*3L@("\O(&]O<',-"B @(" O+W!R;W!E<E]F;W)W87)D M*"!I("D@+R\@=V]N)W0@8V]M<&EL90T*(" @('!R;W!E<E]F;W)W87)D*"!R M968\:6YT/BAI*2 I.PT*(" @("\O<')O<&5R7V9O<G=A<F0H(&-R968\:6YT =/BAI*2 I.R O+R!W;VXG="!C;VUP:6QE#0I]#0H` ` end

Thorsten Ottosen wrote:
won't boost::ref <> "solve" this. (don't bind use &?)
No and no.
(a) My comments about boost::bind comes from http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm
But bind's reference docs seems to use by-value.
Looking at the code, it seems boost::bind uses non-const reference for operator() -- the actual forwarding -- and by-value for arguments to 'bind' itself. So, you should add pass by non-const reference to the list of alternatives. What I think about it is that const-reference prevents you from passing non-const references to constructors of objects you put to container. OTOH, with non-const references you'd break the passing of integer literals -- which is the point of the library. Maybe, you really should support ref<> for passing non-const references. - Volodya

Hi Vladimir, "Vladimir Prus" <ghost@cs.msu.su> wrote in message news:c5dcug$67c$1@sea.gmane.org...
Thorsten Ottosen wrote:
won't boost::ref <> "solve" this. (don't bind use &?)
No and no.
(a) My comments about boost::bind comes from http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm
But bind's reference docs seems to use by-value.
Looking at the code, it seems boost::bind uses non-const reference for operator() -- the actual forwarding -- and by-value for arguments to 'bind' itself.
I must admit I don't get that. I extended rhe example to show the problems (see attachment). As you point out, bind() *silently* compiles code that would not compile if one called the original function with those arguments. IMO, *very* trouplesome. Could the authors of bind/function please comment on why that has been allowed?
So, you should add pass by non-const reference to the list of alternatives.
yeah, that's one of the alternatives discussed in Howard and Dave's paper..
What I think about it is that const-reference prevents you from passing non-const references to constructors of objects you put to container.
only in the sense that you need to use boost::ref<>
OTOH, with non-const references you'd break the passing of integer literals --
any "literal", in fact.
which is the point of the library.
yes.
Maybe, you really should support ref<> for passing non-const references.
Depends on what you mean by support :-) It's already supported by using ref<>. I think that is ok; afterall, reference arguments should not be used that much thoughout code. br Thorsten begin 666 ref.cpp M#0HC:6YC;'5D92 \8F]O<W0O<F5F+FAP<#X-"B-I;F-L=61E(#QI;W-T<F5A M;3X-"B-I;F-L=61E(#QB;V]S="]B:6YD+FAP<#X-"@T*=7-I;F<@;F%M97-P M86-E('-T9#L-"G5S:6YG(&YA;65S<&%C92!B;V]S=#L-"@T*=F]I9"!F;V\H M(&EN="8@:2 I( T*>PT*(" @(&-O=70@/#P@)FD@/#P@(B B.PT*?0T*#0IT M96UP;&%T93P@8VQA<W,@5" ^#0IV;VED(&9O<G=A<F0H(%0@=" I#0I[#0H@ M(" @9F]O*"!T("D[#0I]#0H-"G1E;7!L871E/"!C;&%S<R!4(#X-"G9O:60@ M<')O<&5R7V9O<G=A<F0H(&-O;G-T(%0F('0@*0T*>PT*(" @(&9O;R@@=" I M.PT*?0T*#0II;G0@;6%I;B@I#0I[#0H@(" @:6YT(&D@/2 Q.PT*(" @(&-O M;G-T(&EN="!C:2 ](#$[#0H@(" @8V]U=" \/" F:2 \/" B("([#0H@(" @ M9F]R=V%R9"@@:2 I.R @+R\@;V]P<PT*(" @(&9O<G=A<F0H(&D@*3L@("\O M(&]O<',-"B @(" O+W!R;W!E<E]F;W)W87)D*"!I("D@+R\@=V]N)W0@8V]M M<&EL90T*(" @('!R;W!E<E]F;W)W87)D*"!R968\:6YT/BAI*2 I.PT*(" @ M("\O<')O<&5R7V9O<G=A<F0H(&-R968\:6YT/BAI*2 I.R O+R!W;VXG="!C M;VUP:6QE#0H@(" @8FEN9"@@9F]O+"!I("DH*3L@("\O(&]O<',-"B @("!B M:6YD*"!F;V\L(&-I("DH*3L@+R\@;V]P<PT*(" @(&)I;F0H(&9O;RP@<F5F 8/&EN=#XH:2D@*2@I.R O+R!O:PT*?0T* ` end

Hi Thorsten,
Looking at the code, it seems boost::bind uses non-const reference for operator() -- the actual forwarding -- and by-value for arguments to 'bind' itself.
I must admit I don't get that. I extended rhe example to show the problems (see attachment). As you point out, bind() *silently* compiles code that would not compile if one called the original function with those arguments. IMO, *very* trouplesome.
What I was saying is that bind uses non-const reference for operator(), so if you use: bind(foo, _1)(i); bind( foo, _1 )(ci); then it will work ok. In fact, first one compiles and the second one does not. And, BTW, "foo(i)" compiles just fine too, so your 'proper_forward(i)' should compile too, but it does not. As for bind(foo, i)(); bind(foo, ci)(); I don't have any opinion yet.
What I think about it is that const-reference prevents you from passing non-const references to constructors of objects you put to container.
only in the sense that you need to use boost::ref<>
Ah, since you only forward arguments boost::ref<> will work transparently and you never need to unwrap_reference in the library code.
OTOH, with non-const references you'd break the passing of integer literals --
any "literal", in fact.
Yes, I've used "integer" for example only.
Maybe, you really should support ref<> for passing non-const references.
Depends on what you mean by support :-) It's already supported by using ref<>. I think that is ok; afterall, reference arguments should not be used that much thoughout code.
I agree. In fact, my previous post was just a long-winded way to say that while in general non-const references might be preferrable, for this library const references are better. - Volodya

"Vladimir Prus" <ghost@cs.msu.su> wrote in message news:c5dpev$rrt$1@sea.gmane.org... [snip]
What I was saying is that bind uses non-const reference for operator(), so if you use:
bind(foo, _1)(i); bind( foo, _1 )(ci);
then it will work ok. In fact, first one compiles and the second one does not.
yep.
And, BTW, "foo(i)" compiles just fine too, so your 'proper_forward(i)' should compile too, but it does not.
yes, but there is a huge difference between compiling wrong code silentltly and rejecting ok code. The use of ref() nicely documents that an address is taken.
As for
bind(foo, i)(); bind(foo, ci)();
I don't have any opinion yet.
I guess I didn't know that I was "misusing" bind(). Anyway, I find it wrong that bind(foo,_1)(i) and bind(foo,i)() differs. br Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
I don't have any opinion yet.
I guess I didn't know that I was "misusing" bind(). Anyway, I find it wrong that bind(foo,_1)(i) and bind(foo,i)() differs.
Naturally it has to differ. bind(foo,i) needs to take a copy of i, or we wouldn't be able to do things like: int square(int); function<void(void)> f(int x) { return bind(square, x * 5); } -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:ufzb9ifv8.fsf@boost-consulting.com...
"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
I don't have any opinion yet.
I guess I didn't know that I was "misusing" bind(). Anyway, I find it wrong that bind(foo,_1)(i) and bind(foo,i)() differs.
Naturally it has to differ. bind(foo,i) needs to take a copy of i, or we wouldn't be able to do things like:
int square(int);
function<void(void)> f(int x) { return bind(square, x * 5); }
My point is that if the prototype was void square( int& ); then function< void(void) > f( int x ) { return bind( square, x*5 ); } should not compile. It should only compile with a call to ref(). br Thorsten

Thorsten Ottosen wrote:
My point is that if the prototype was
void square( int& );
then
function< void(void) > f( int x ) { return bind( square, x*5 ); }
should not compile.
Why should it not compile? int increment(int & x) { return ++x; } template<class F> void test_nonconst(F f) { std::cout << f() << '\n'; std::cout << f() << '\n'; std::cout << f() << '\n'; } template<class F> void test_const(F const & f) { std::cout << f() << '\n'; std::cout << f() << '\n'; std::cout << f() << '\n'; } int main() { test_nonconst( bind(increment, 0) ); // 1 2 3 test_const( bind(increment, 0) ); // compile-fail } It's as if you've written struct increment { int a1_; int operator()() { return ++a1_; } }; yourself.

"Peter Dimov" <pdimov@mmltd.net> wrote in message news:001501c42095$eb0425b0$1d00a8c0@pdimov2...
Thorsten Ottosen wrote:
My point is that if the prototype was
void square( int& );
then
function< void(void) > f( int x ) { return bind( square, x*5 ); }
should not compile.
Why should it not compile?
consider instead void write_to( string& s ) { s += " foo"; } string s = "bar"; bind( write_to, s )(); cout << s; // won't print "bar foo" br Thorsten

Thorsten Ottosen wrote:
"Peter Dimov" <pdimov@mmltd.net> wrote in message news:001501c42095$eb0425b0$1d00a8c0@pdimov2...
Thorsten Ottosen wrote:
My point is that if the prototype was
void square( int& );
then
function< void(void) > f( int x ) { return bind( square, x*5 ); }
should not compile.
Why should it not compile?
consider instead
void write_to( string& s ) { s += " foo"; }
string s = "bar"; bind( write_to, s )(); cout << s; // won't print "bar foo"
That's how bind works. All arguments in "bind(write_to, s)" are copied, including 'write_to'. If you make 'write_to' a stateful function object, "bind(write_to, s)()" won't update 'write_to' either.

"Peter Dimov" <pdimov@mmltd.net> wrote in message news:000d01c420a3$e68d6240$1d00a8c0@pdimov2...
Thorsten Ottosen wrote: [snip]
Why should it not compile?
consider instead
void write_to( string& s ) { s += " foo"; }
string s = "bar"; bind( write_to, s )(); cout << s; // won't print "bar foo"
That's how bind works. All arguments in "bind(write_to, s)" are copied, including 'write_to'. If you make 'write_to' a stateful function object, "bind(write_to, s)()" won't update 'write_to' either.
But isn't it possible to reject compiling the above example? It's really not what I would expect people to expect, especially since bind(write,_1)(s) differs. br Thorsten

Thorsten Ottosen wrote:
"Peter Dimov" <pdimov@mmltd.net> wrote in message news:000d01c420a3$e68d6240$1d00a8c0@pdimov2...
Thorsten Ottosen wrote: [snip]
Why should it not compile?
consider instead
void write_to( string& s ) { s += " foo"; }
string s = "bar"; bind( write_to, s )(); cout << s; // won't print "bar foo"
That's how bind works. All arguments in "bind(write_to, s)" are copied, including 'write_to'. If you make 'write_to' a stateful function object, "bind(write_to, s)()" won't update 'write_to' either.
But isn't it possible to reject compiling the above example? It's really not what I would expect people to expect, especially since bind(write,_1)(s) differs.
Yes, of course it is possible to reject the example. But I don't want to reject it. It's useful. bind(write, _1)(s) is a false analogy. bind is never used like that outside of toy illustrative examples. You always pass bind(write, _1) to someone else, and bind(f, a) always makes copies of f and a for lifetime reasons, regardless of their types. Consider using lambda::bind, which fails the above example. Isn't competition wonderful?

Hi Peter, [snp]
Yes, of course it is possible to reject the example. But I don't want to reject it. It's useful.
Ok. Could you present an example? Let me explain what bothers me. I simply fail to see why a call-back created with bind() should silently behave differently from what it forwards to. IMO that will create confusion.
bind(write, _1)(s) is a false analogy.
even so, it won't prove the current strategy is right, merely mine is wrong :-)
bind is never used like that outside of toy illustrative examples. You always pass bind(write, _1) to someone else, and bind(f, a) always makes copies of f and a for lifetime reasons, regardless of their types.
ok, but I do assume that binding one parameter out of eg two is used sometimes.
Consider using lambda::bind, which fails the above example. Isn't competition wonderful?
Yes, but only when the customer gets a better service :-) br Thorsten

Thorsten Ottosen wrote:
Hi Peter,
[snp]
Yes, of course it is possible to reject the example. But I don't want to reject it. It's useful.
Ok. Could you present an example?
This feature of bind is used to create stateful function objects. In a "real" lambda facility it corresponds to a local static variable: for_each( first, last, lambda(v) { static int x = 0; f(v, ++x); } ); The bind equivalent is for_each( first, last, bind( f, _1, bind(incr, 0) ) ); It calls f(first[0], 1), f(first[1], 2), and so on.
Let me explain what bothers me. I simply fail to see why a call-back created with bind() should silently behave differently from what it forwards to. IMO that will create confusion.
Bind's emphasis is on usefulness, not hand-holding. Its learning curve is inherently steep and more importantly, it simply cannot be flattened by making bind less useful. To focus on how to make it less confusing would mean to penalize advanced users while, at the same time, not helping beginners in any significant way.

"Peter Dimov" <pdimov@mmltd.net> wrote in message news:002101c4214f$0cfb5f30$1d00a8c0@pdimov2...
Thorsten Ottosen wrote:
Hi Peter,
[snp]
Yes, of course it is possible to reject the example. But I don't want to reject it. It's useful.
Ok. Could you present an example?
This feature of bind is used to create stateful function objects. In a "real" lambda facility it corresponds to a local static variable:
for_each( first, last, lambda(v) { static int x = 0; f(v, ++x); } );
The bind equivalent is
for_each( first, last, bind( f, _1, bind(incr, 0) ) );
ok, but couldn't incr() just be defined as 'int incr( int i ) { return i + 1; }' ? Anyway, it is not the possibility of having "local static" data in function objects we are arguing about, its about what to pass that data to.
Bind's emphasis is on usefulness, not hand-holding.
good frase :-)
Its learning curve is inherently steep and more importantly, it simply cannot be flattened by making bind less useful.
I guess the current design gives maximal power; so it it seems ok. Requering that the user calls bind( f, local_copy( i ) ) would document that the programmer knows that f takes a reference, but that it can act on a copy. However, once you know the mechanism, you would be irritated by such constraints. br Thorsten

Vladimir Prus <ghost@cs.msu.su> writes:
Looking at the code, it seems boost::bind uses non-const reference for operator() -- the actual forwarding -- and by-value for arguments to 'bind' itself.
Note that templated non-const references will bind to const and non-const lvalues (with different 'T' deduction). The only things they won't bind to are rvalues. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Thorsten I trust that you are aware of the following quoted, from MSDN for all Microsoft C++ compilers " As can be seen in the Visual C++ source file, uncaught.cpp, uncaught_exception always returns false even in cases where the standard specifies that it should return true. See Knowledge Base article Q242192 for more information. " Keith -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Thorsten Ottosen Sent: 10 April 2004 11:22 To: boost@lists.boost.org Subject: [boost] Re: Assignment library: review Hi Gennadiy, [snip]
4. ~fixed_size_assigner This method may throw an exception. Does it always safe to rely on uncaught_exception call?
No, it is not always safe, but the unsafe stuff happens if you use it in a destructor; not very likely. Sutter has an article about it. [snip]

Hi Keith, "Keith Burton" <kb@xtramax.co.uk> wrote in message news:KBDUALJnY2bH6qNwqDt00000001@xtramax.co.uk...
Thorsten
I trust that you are aware of the following quoted, from MSDN for all Microsoft C++ compilers
Thanks for the pointer. I must admit I always assume the compiler is a C++ compiler :-)
" As can be seen in the Visual C++ source file, uncaught.cpp, uncaught_exception always returns false even in cases where the standard specifies that it should return true.
See Knowledge Base article Q242192 for more information. "
dreadful. br Thorsten
participants (6)
-
David Abrahams
-
Gennadiy Rozental
-
Keith Burton
-
Peter Dimov
-
Thorsten Ottosen
-
Vladimir Prus