
The review of Assignment Library library, written by Thorsten Ottosen 2003 (nesotto@cs.auc.dk) starts today(April 1, 2004)and runs for 10 days. Latest version of the library is available at: http://groups.yahoo.com/group/boost/files/assignment/ (204 kB) or in the sandbox. What it is? The purpose of this library is to make it easy to fill containers with data by overloading operator the comma, () and operator()(). Example: To fill a vector with values you write: #include <boost/assign/stl.hpp// for operator+=() #include <vector> using namespace std; using namespace boost::assignment; vector<intvalues; values += 1,2,3,4,5,6,7,8,9; values += foo1(), foo2(), foo3(); History of the project: The idea for an initialization library is not new . The functionality of this library resembles Leor Zolman's STL Container Initialization Library a great deal, but it does not rely on string passing to achieve its goals. The library is non-intrusive and puts only a minimum of requirements on its supported classes. (change classes to types) The Initialization Library overloads the comma operator in a safe manner by letting free standing functions return an object that is responsible for the initialization. Therefore it takes explicit action from the programmer to begin using the overloaded operator,(). The operator comma is never overloaded for user-defined types. Portability: Library has been successfully compiled and tested with MVC++ 6.0, MVC++ 7.0, MVC++ 7.1, GCC 3.2 (under Cygwin) Comeau 4.3.0.1, Intel ICC 7.1 and Intel ICC 8.0. There are known limitation on platforms not supporting partial template specialization. Review Comments: Your review comments are welcomed. Found problems and suggestions for documentation are highly sought. Requests for new features requests will shape the way this library will evolve in future. 1. Where should the main libraries header files be placed. This is header only library and should be fairly easy to manage.Should it be placed in the utilty folder or its own folder? 2. Should the headers be broken up? This library has extensions to boost::array, boost::ublas and boost::graph. Should those headers be placed in their respective folder or kept together with the headers associated with the main Assignment library headers. Or, should the boost library extensions remain just as examples of how to extend the library. 3. Should the fixed_size_asssigner only throw on out_of_bounds exception or should it default initialize the remainning elements? Two classes can throw an exception in their destructor. This is done when detecting eg. a boost::array has not been initialized with enough elements. Should this be replaced by default initializing the remaining elements? 4. This library needs to use the boost test framework. Review Manager Tom Brinkman reportbase@yahoo.com __________________________________ Do you Yahoo!? Yahoo! Small Business $15K Web Design Giveaway http://promotions.yahoo.com/design_giveaway/

I like the idea. However, I argue with some design decisions. The biggest problem is that it's too easy to add operator+= to any container-like class. For example, this program doesn't compile: struct not_container { typedef int value_type; template<class T> void operator+=(T) {} }; #include <boost/assign/stl.hpp> using namespace boost::assignment; int main() { not_container v; v += 1, 3; } -- Alexander Nasonov Independent Developer and Consultant

Hi Alexander, "Alexander Nasonov" <alnsn-mycop@yandex.ru> wrote in message news:c4hmul$uuc$1@sea.gmane.org...
I like the idea. However, I argue with some design decisions. The biggest problem is that it's too easy to add operator+= to any container-like class.
What would you prefer then?
For example, this program doesn't compile:
struct not_container { typedef int value_type;
template<class T> void operator+=(T) {} };
#include <boost/assign/stl.hpp> using namespace boost::assignment;
int main() { not_container v; v += 1, 3; insert(v)(1)(3); // should work }
best regards Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:c4i8sj$947$1@sea.gmane.org...
Hi Alexander,
"Alexander Nasonov" <alnsn-mycop@yandex.ru> wrote in message news:c4hmul$uuc$1@sea.gmane.org...
I like the idea. However, I argue with some design decisions. The biggest problem is that it's too easy to add operator+= to any container-like class.
What would you prefer then?
I also believe that providing template method for global operator += is not good idea. What you could do is to provide an operator += specialization for stl containers and support initialization in a form: init( C ) += ... as a generic solution. Gennadiy.

"Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote in message news:c4ifep$lpt$1@sea.gmane.org...
"Alexander Nasonov" <alnsn-mycop@yandex.ru> wrote in message news:c4hmul$uuc$1@sea.gmane.org...
I like the idea. However, I argue with some design decisions. The biggest problem is that it's too easy to add operator+= to any container-like class.
What would you prefer then?
I also believe that providing template method for global operator += is not good idea.
its not global. And you have to include the specific assign/stl.hpp header.
What you could do is to provide an operator += specialization for stl containers and support initialization in a form:
init( C ) += ...
as a generic solution.
If you looked at the lib, you would find that it is already there; it's called insert(). br Thorsten

Thorsten Ottosen wrote:
its not global. And you have to include the specific assign/stl.hpp header.
This header doesn't live alone. It's in TU together with other classes. When users writes using namespace boost::assignment, the operator+= is introduced automatically to every class that has value_type in its definition. I wish we could write something like using boost::assignment::introduce_container_template<vector>; to introduce operator+= only to vectors. -- Alexander Nasonov Independent Developer and Consultant

"Alexander Nasonov" <alnsn-mycop@yandex.ru> wrote
Thorsten Ottosen wrote:
its not global. And you have to include the specific assign/stl.hpp header.
My problem with assignment lib is shown in following. in a nutshell I might want to use assign , but not +=, from assignment lib. Currently not possible. Personally I dont like use of += function for init anyways. Nevertheless for maps etc and matrices etc it might be useful. OTOH Adding brackets to each initialiser for assign is a bit ugly... but appreciate not much you can do about it. regards Andy Little -------------- #include <iostream> #include <vector> // stream output for vector of t #include "test.hpp" #include "pqs/pqs.hpp" // if += used for another purpose cant use assign lib // following cant both be true #define USE_ARITH_PLUS_EQ 1 #define USE_ASSIGN_LIB 0 #if USE_ASSIGN_LIB #include "boost/assign.hpp" using namespace boost::assignment; // bring asignment libs 'operator+=()' into scope #endif #if USE_ARITH_PLUS_EQ // Dont want assignment lib += semantics, // rather want to add a value to every element in a vector template <typename T> std::vector<T>& operator +=(std::vector<T>& vect, T t) { std::vector<T>::iterator iter= vect.begin(); while(iter != vect.end()){ *iter += t; ++iter; } return vect; } #endif using namespace pqs; int main() { std::vector<pqs::q_length::mm> v; // ok cant use += assignment semantics here // but maybe would like to use assign function #if USE_ASSIGN_LIB assign( v ) (pqs::q_length::mm(1)), (pqs::q_length::mm(2)), (pqs::q_length::mm(3)), (pqs::q_length::mm(4)); #else v.push_back(pqs::q_length::mm(1)); v.push_back(pqs::q_length::mm(2)); v.push_back(pqs::q_length::mm(3)); v.push_back(pqs::q_length::mm(4)); #endif std::cout << v <<'\n'; #if USE_ARITH_PLUS_EQ // cant do this and use assignment lib v += q_length::mm(1); #endif std::cout << v <<'\n'; }

My problem with assignment lib is shown in following. in a nutshell I might want to use assign , but not +=, from assignment
"Andy Little" <andy@servocomm.freeserve.co.uk> wrote lib.
Currently not possible.
Right scratch that. OTOH remove using boost::assignment directive from example and qualify and works ok. Apologies Andy Little

Gennadiy Rozental wrote:
"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:c4i8sj$947$1@sea.gmane.org...
Hi Alexander,
"Alexander Nasonov" <alnsn-mycop@yandex.ru> wrote in message news:c4hmul$uuc$1@sea.gmane.org...
I like the idea. However, I argue with some design decisions. The biggest problem is that it's too easy to add operator+= to any container-like class.
What would you prefer then?
I also believe that providing template method for global operator += is not good idea.
What you could do is to provide an operator += specialization for stl containers and support initialization in a form:
init( C ) += ...
as a generic solution.
I definitely second that. Of course, there's an insert(c) in the library, but that works like insert(cont) (a)(b)(c); I would like: insert(count) += a,b,c; Seems much more straightforward, and doesn't overload operator += for a containers, which I think could turn out to be dangerous. Best, John

Hi John, "John Torjo" <john.lists@torjo.com> wrote in message news:4071A5B0.4090109@torjo.com...
Gennadiy Rozental wrote: [snip]
What you could do is to provide an operator += specialization for stl containers and support initialization in a form:
init( C ) += ... [snip] I definitely second that.
In the very beginning it was like this. But people back then liked the "global" operator+=() :-)
Of course, there's an insert(c) in the library, but that works like insert(cont) (a)(b)(c);
I would like: insert(count) += a,b,c;
then you would like operator=() too, right?
Seems much more straightforward, and doesn't overload operator += for a containers, which I think could turn out to be dangerous.
Could you tell me what the "danger" is? Afterall, if the container happens to have operator+= it's either a compilation error or not; in the latter case you simply have two version with different semantics. br Thorsten

What do you think of: vector<int> v; repeat(bind(vector<int>::push_back, &v, _1)) , 3, 4, 5; I like it, being explicit and more general. Is something like this already in boost? Bruno Martínez

Bruno Martínez Aguerre wrote:
What do you think of:
vector<int> v; repeat(bind(vector<int>::push_back, &v, _1)) , 3, 4, 5;
I like it, being explicit and more general. Is something like this already in boost?
Bruno Martínez
I'd prefer to have on-fly container. Something like this: std::copy( on_fly % 1 % 2 % 3, on_fly_end<int>(), back_inserter<int>(v)); Not as cool as v += 1, 2, 3; but might have some advantages. -- Alexander Nasonov Independent Developer and Consultant

Thorsten Ottosen wrote:
I'd prefer to have on-fly container. Something like this:
std::copy( on_fly % 1 % 2 % 3, on_fly_end<int>(), back_inserter<int>(v));
Not as cool as v += 1, 2, 3; but might have some advantages.
What would the advantages be? This have advantage when the container is not available, only iterators range.
template<class Iter> void one_two_three(Iter begin, Iter end) { assert(distance(begin, end) >= 3); copy(on_fly % 1 % 2 % 3, on_fly_end<int>(), begin); } It has some serious problem, though. For example, in find(on_fly % 1 % 2 % 3, on_fly_end<int>(), 2); return value points to temporary. -- Alexander Nasonov Independent Developer and Consultant

Hi Bruno,
"Bruno Martínez Aguerre" <br1@internet.com.uy> wrote in message news:opr5zufwh4s0jexp@news.gmane.org... What do you think of:
vector<int> v; repeat(bind(vector<int>::push_back, &v, _1)) , 3, 4, 5;
I like it, being explicit
true, but I hope it is not too difficult to know what my operator/functions do.
and more general. Is something like this already in boost?
It wasn't quite in my original scope for the library. If there is enough support for the idea, I could add a class with a callback instead of ADL of insert(). Then people can craft stuff like yours above. br Thorsten

Tom Brinkman wrote:
The review of Assignment Library library, written by Thorsten Ottosen 2003 (nesotto@cs.auc.dk) starts today(April 1, 2004)and runs for 10 days.
Latest version of the library is available at: http://groups.yahoo.com/group/boost/files/assignment/ (204 kB) or in the sandbox.
What it is?
The purpose of this library is to make it easy to fill containers with data by overloading operator the comma, () and operator()().
[Snip] Hi, This isn't a formal review, just some initial comments based on a quick test of the lib. * I definitely think that the stl.hpp header should be split up to provide finer granularity (altough possibly retaining a convenience wrapper.) * Have you read this article by Andrei Alexandrescu? http://www.moderncppdesign.com/publications/inline_containers.html One advantage of an approach like the above, which I personally value, is the ability to do const-initialization: vector<foo> const v = make_vec(...); * Another variant similar to the above is to use a function-template as a pure "type grabber" and provide a conversion operator for the chaining proxy. This allows syntax like: container<T> const c = init(c)(..)(..) ; This technique is used in Leor Z's lib, as I'm sure you're aware. A third option (also used by Leor) is to have a fully templatized conversion operator. I'd vote for the "middle road" solution above though. Would be interesting to hear your opinion and rationale regarding this. Regardless of implementational technique and syntax finally chosen, I'd Really like it to support const initialization. (is that the correct term btw?) * What's the reason for removing the enum_* initialization mentioned in your Codeproject article? http://www.codeproject.com/vcpp/stl/PGIL.asp Is something similar planned to be added later? * insert_assigner.hpp boost/call_traits.hpp is included but not used. * Documentation nitpick: The "history and rationale" part doesn't have a quick-link from the index. * I think the documentation for initialization of boost::graph, uBlas etc should be moved to separate chapters (files). The lib will most surely grow and a separated structure for adding docs for new components could just as well be used right away. * Boost.PP could/should be used to provide configurable upper limits for number of parameters. * Perhaps use concept_check to ensure that the default version of make_insertion only operates on Sequences? Hope this makes alteast some sense to you, I'll try to tinker with the lib some more and hopefully return :) Regards // Fredrik Blomqvist

Hi Fredrik, "Fredrik Blomqvist" <fredrik_blomqvist@home.se> wrote in message news:c4vclu$dc$1@sea.gmane.org...
* I definitely think that the stl.hpp header should be split up to provide finer granularity (altough possibly retaining a convenience wrapper.)
ok.
* Have you read this article by Andrei Alexandrescu? http://www.moderncppdesign.com/publications/inline_containers.html
I might have a long time ago. Anyway, the goal seems to be different. His problem is "How can you pass a varying number of arguments to a function and maintain type safety?"
One advantage of an approach like the above, which I personally value, is the ability to do const-initialization: vector<foo> const v = make_vec(...);
True. I think my view has been that it could be done by calling a function, but that would not give the direct overview you're talking about. I can see two disadvanteges: 1. performance (not important to most) 2. loss of generality: The implementer needs to inherit from each supported container XX + write make_XX
* Another variant similar to the above is to use a function-template as a pure "type grabber" and provide a conversion operator for the chaining proxy. This allows syntax like: container<T> const c = init(c)(..)(..) ; This technique is used in Leor Z's lib, as I'm sure you're aware.
yes. It looks a bit wierd when using a comma list. If you have a const sequence, array<T,x> would probably do, right?
A third option (also used by Leor) is to have a fully templatized conversion operator. I'd vote for the "middle road" solution above though.
Ok, I see no problems with a specific utility for initialization. It will save people the need for writing a function.
, I'd Really like it to support const initialization. (is that the correct term btw?)
I'm not sure, but I would just call it copy-initialization of a const object.
* What's the reason for removing the enum_* initialization mentioned in your Codeproject article? http://www.codeproject.com/vcpp/stl/PGIL.asp Is something similar planned to be added later?
It's not planned because the stuff got a bad reception. In particular, it overlaps with boost::counting_iterator, although I still think counting iterator requires too much typing. And since I went away from suporting any form of initialization, I called the lib "assignment" instead (since some were against calling it initialization in a broader sense).
* I think the documentation for initialization of boost::graph, uBlas etc should be moved to separate chapters (files). The lib will most surely grow and a separated structure for adding docs for new components could just as well be used right away.
Ok, there is a general question that also must be answered; should these things even be in this lib (compared to being in the libs they support)?
* Boost.PP could/should be used to provide configurable upper limits for number of parameters.
ok. Thanks for your comments br Thorsten

[Note: I initially intended to send this mail couple of days ago, but I've been offline during easter. Hence a couple of the comments have since become adressed. I choose to post anyway for completeness.] Thorsten Ottosen wrote:
* Have you read this article by Andrei Alexandrescu? http://www.moderncppdesign.com/publications/inline_containers.html
I might have a long time ago. Anyway, the goal seems to be different. His problem is: "How can you pass a varying number of arguments to a function and maintain type safety?"
Yes that's understood. But please note that Andrei's code can be used for assignment/initialization purposes also.
One advantage of an approach like the above, which I personally value, is the ability to do const-initialization: vector<foo> const v = make_vec(...);
True. I think my view has been that it could be done by calling a function, but that would not give the direct overview you're talking about. Exactly. I believe it greatly benefits usability.
I can see two disadvanteges: 1. performance (not important to most)
Yes, I thought about this. Have not made any measurements though. If not the optimizer (RVO) handles it good enough some "move-magic" should be able to help(?).
2. loss of generality: The implementer needs to inherit from each supported container XX + write make_XX
Well, not quite (IIUC). Andrei's code uses inheritance but same syntax can be acchieved using conversion operators also. Thus an implementation can still forward to a simple insert_elem<> to be provided by the end user.
* Another variant similar to the above is to use a function-template as a pure "type grabber" and provide a conversion operator for the chaining proxy. This allows syntax like: container<T> const c = init(c)(..)(..) ; This technique is used in Leor Z's lib, as I'm sure you're aware.
yes. It looks a bit wierd when using a comma list. If you have a const sequence, array<T,x> would probably do, right?
hmm, not sure I understand? You mean the fact that a comma list would need extra parenthesis?
* What's the reason for removing the enum_* initialization mentioned in your Codeproject article? http://www.codeproject.com/vcpp/stl/PGIL.asp Is something similar planned to be added later?
It's not planned because the stuff got a bad reception. In particular, it overlaps with boost::counting_iterator, although I still think counting iterator requires too much typing.
Ok, sounds reasonable. I was mostly curious since no rationale was given. Easier to Add things later than Remove later...
And since I went away from suporting any form of initialization, I called the lib "assignment" instead (since some were against calling it initialization in a broader sense).
I view both initialization and assignment as so closely related that a separation feels artificial. This is a _convenience_ util after all. In the same sense being able to construct inline-containers for function calls is just a nice "spin-off" :)
* I think the documentation for initialization of boost::graph, uBlas etc should be moved to separate chapters (files). The lib will most surely grow and a separated structure for adding docs for new components could just as well be used right away.
Ok, there is a general question that also must be answered; should these things even be in this lib (compared to being in the libs they support)?
I think this issue should be discussed more broadly since it affects more than just this lib. The upcoming Boost.Serialization lib will for example face exactly the same issues. In the short term though I'd say they should just go into the assignment lib, and then later possibly relocated according to a boost-wide policy. //Fredrik Blomqvist

"Fredrik Blomqvist" <fredrik_blomqvist@home.se> wrote in message news:c5ceon$qbm$1@sea.gmane.org... [snip]
I might have a long time ago. Anyway, the goal seems to be different. His problem is: "How can you pass a varying number of arguments to a function and maintain type safety?"
Yes that's understood. But please note that Andrei's code can be used for assignment/initialization purposes also.
yes. If I have to make individual headers anyway, it's quite easy to supply make_vector() etc.
I can see two disadvanteges: [snip] 2. loss of generality: The implementer needs to inherit from each supported container XX + write make_XX
Well, not quite (IIUC). Andrei's code uses inheritance but same syntax can be acchieved using conversion operators also. Thus an implementation can still forward to a simple insert_elem<> to be provided by the end user.
yes.
* Another variant similar to the above is to use a function-template as a pure "type grabber" and provide a conversion operator for the chaining proxy. This allows syntax like: container<T> const c = init(c)(..)(..) ; This technique is used in Leor Z's lib, as I'm sure you're aware.
yes. It looks a bit wierd when using a comma list. If you have a const sequence, array<T,x> would probably do, right?
hmm, not sure I understand? You mean the fact that a comma list would need extra parenthesis?
This looks a bit wierd const vector<int> v = init( v ),1,2,3,4,5; but not horrible wierd. Now if you do have a const sequence, array would do just fine const array<int,5> a = {1,2,3,4,5}; (execpt that this don't work in an initializer list) [snip]
And since I went away from suporting any form of initialization, I called the lib "assignment" instead (since some were against calling it initialization in a broader sense).
I view both initialization and assignment as so closely related that a separation feels artificial. This is a _convenience_ util after all. In the same sense being able to construct inline-containers for function calls is just a nice "spin-off" :)
So you would support Boost.Initialization ?
* I think the documentation for initialization of boost::graph, uBlas etc should be moved to separate chapters (files). The lib will most surely grow and a separated structure for adding docs for new components could just as well be used right away.
Ok, there is a general question that also must be answered; should these things even be in this lib (compared to being in the libs they support)?
I think this issue should be discussed more broadly since it affects more than just this lib. The upcoming Boost.Serialization lib will for example face exactly the same issues. In the short term though I'd say they should just go into the assignment lib, and then later possibly relocated according to a boost-wide policy.
ok. br Thorsten

Tom Brinkman wrote:
The review of Assignment Library library, written by Thorsten Ottosen 2003 (nesotto@cs.auc.dk) starts today(April 1, 2004)and runs for 10 days.
Latest version of the library is available at: http://groups.yahoo.com/group/boost/files/assignment/ (204 kB) or in the sandbox.
My review doesn't pretend to be complete. I took a quick look at documentation and at a couple of header files. I didn't analyze at all neither BGL nor ublas related features. I think the library cannot be accepted in its current state because library version of operator+= is introduced to _every_ class having nested value_type when one writes using boost::assignment (see my other reply for details). One possible solution would be a special container_traits class: // in insert_assigner.hpp // right before operator+= // template<class Container> struct container_traits { typedef void value_type; // SFINAE fails by default }; template<class T, class Alloc> struct container_traits< ::std::vector<T,Alloc> > { typedef T value_type; }; // specializations for other STL containers // ... template< typename C > inline insert_assigner<C> operator+=( C& c, const typename container_traits<C>::value_type& v ) { return insert_assigner<C>( c, v ); } -- Alexander Nasonov Independent Developer and Consultant

Hi Alexander, Thanks for your comment.
One possible solution would be a special container_traits class: [snip example]
That will only work if I include all releavnt standard headers. Some people want's to have specializations too, and it seems like the most reasonable thing to do. It will imply a "one container, one header" policy and remove the possibility of the "all std containers (except stack,queue,pri-queue), one header" policy. br Thorsten

Tom Brinkman wrote:
The review of Assignment Library library, written by Thorsten Ottosen 2003 (nesotto@cs.auc.dk) starts today(April 1, 2004)and runs for 10 days.
After reading the latest posts by Thorsten and seeing that my previous concerns (mostly regarding initialization) most likely will be adressed in the final version of the lib, I feel I can now vote _for acceptance_. (please see my earlier posts for my technical review) I assume a post-review version of the lib can be examined and discussed before final inclusion. Thank's to Thorsten - Fortsatt Dejlig Påske :) // Fredrik Blomqvist
participants (8)
-
Alexander Nasonov
-
Andy Little
-
Bruno Martínez Aguerre
-
Fredrik Blomqvist
-
Gennadiy Rozental
-
John Torjo
-
Thorsten Ottosen
-
Tom Brinkman