[mini-review] Update of Boost.Assign (13th-19th of June)

Dear Boost Developers and Users, Erwann Rogard has implemented an update to Boost.Assign which we shall evaluate during the next week. His extensions allows one to write code like the following: (A) A list of references (to temporaries, in this example): boost::array<int,8> a = cref_csv( 1,5,3,4,2,9,0,7 ) (B) Chained ranges: vector<int> v = vector<int>( 3,1 ) && vector<int>( 3,2 ); If you have comments and suggestions about these new features, please submit a small review or voice your oppinion on the Boost developer list. If you have other feedback for Boost.Assign, now would be a good time to mention them too. If you submit a review, please follow the guidelines here: http://www.boost.org/community/reviews.html#Comments To access the new docs, please see https://svn.boost.org/svn/boost/sandbox/statistics/support/libs/assign/doc/i... To access the new code, please see https://svn.boost.org/svn/boost/sandbox/statistics/support/boost/assign/ best regards Thorsten Ottosen, Review Manager

On 13 Jun 2010, at 21:57, Thorsten Ottosen wrote:
If you have comments and suggestions about these new features, please submit a small review or voice your oppinion on the Boost developer list. If you have other feedback for Boost.Assign, now would be a good time to mention them too.
While independant of this change, I believe Boost.Assign may be ideally suited to use variadic templates. I am already making use of a variadic push_back and container construction, like: push_back(v,1,2,3,4); and: make<std::vector>(1,2,3,4,5); // Makes a std::vector<int> containing 1,2,3,4,5 make_list(1,2,3,4,5); // Makes a list which can be assigned to any standard container, filling it with 1,2,3,4,5. I do not know if it would be best for these to be integrated into the existing library, or kept separate. Chris

On 13/06/10 21:57, Thorsten Ottosen wrote:
Dear Boost Developers and Users,
Erwann Rogard has implemented an update to Boost.Assign which we shall evaluate during the next week. His extensions allows one to write code like the following:
(A)
A list of references (to temporaries, in this example):
boost::array<int,8> a = cref_csv( 1,5,3,4,2,9,0,7 )
I'm curious: we have three list_of functions (list_of, ref_list_of and cref_list_of) but only two of them have analogous csv functions (ref_csv and cref_csv). Why is there no simple csv function, taking arguments by value? John Bytheway

I'm curious: we have three list_of functions (list_of, ref_list_of and cref_list_of) but only two of them have analogous csv functions (ref_csv and cref_csv). Why is there no simple csv function, taking arguments by value?
John Bytheway
You are right that csv is a new interface and it seems logical that it should be available for passing arguments by value. I guess it wouldn't be an insurmountable task to overload csv() on the number of arguments, internally calling list_of(), and returning its results. That's approximately how ref_csv() and ref_list_of() relate to each other. What is complicating things, however, is that list_of() itself is overloaded on the number of arguments. list_of<T>(x,y)(z,w) creates an anonymous list of elements created like this : T(x,y) and T(z,w). If you want to achieve the same thing with cref_csv, you have to do: cref_csv(T(x,y),T(z,w))

On 16/06/10 02:08, er wrote:
You are right that csv is a new interface and it seems logical that it should be available for passing arguments by value.
I guess it wouldn't be an insurmountable task to overload csv() on the number of arguments, internally calling list_of(), and returning its results. That's approximately how ref_csv() and ref_list_of() relate to each other.
That sounds sensible. I think there should be such a function.
What is complicating things, however, is that list_of() itself is overloaded on the number of arguments. list_of<T>(x,y)(z,w) creates an anonymous list of elements created like this : T(x,y) and T(z,w).
If you want to achieve the same thing with cref_csv, you have to do: cref_csv(T(x,y),T(z,w))
I don't understand why that is a complication. In this case it would be logical for the user to use list_of instead (at least from the perspective of amount of typing). On a related subject (and perhaps slightly beyond the scope of a mini-review), have you considered a perfect forwarding version of any of these functions? Or even move-enabling the by-value ones? You're already justifying the _ref versions on grounds of speed; this would be the logical next step in that direction. Personally I would be happy to have such only in C++0x and not bother with move-emulation in C++03, but then I don't program in C++03 any more if I can possibly help it :). John Bytheway

John Bytheway wrote:
I guess it wouldn't be an insurmountable task to overload csv() on the number of arguments, internally calling list_of(), and returning its
That sounds sensible. I think there should be such a function.
OK, will take that into consideration but more about that below. Meanwhile, it's already possible to do std::vector<int> vec = (list_of(1),2,3);
What is complicating things, however, is that list_of() itself is overloaded on the number of arguments. list_of<T>(x,y)(z,w) creates an anonymous list of elements created like this : T(x,y) and T(z,w).
If you want to achieve the same thing with cref_csv, you have to do: cref_csv(T(x,y),T(z,w))
I don't understand why that is a complication. In this case it would be logical for the user to use list_of instead (at least from the perspective of amount of typing).
I would tend to always use cref_list_of(a)(b)(c) rather than list_of(a)(b)(c), because the first one is generally faster, see https://svn.boost.org/svn/boost/sandbox/statistics/support/libs/assign/doc/s... https://svn.boost.org/svn/boost/sandbox/statistics/support/libs/assign/doc/s... and offers a more comprehensive interface such as indexing (operator[]). The function list_of() shines, however, in other areas, such as being able to call typedef std::pair<const k_type,t_type> pair_; map = list_of<pair_>(a,b)(c,d); (by the way this is how map_list_of(a,b)(c,d) is implemented) whereas the alternative calls for more typing: map = cref_list_of(pair_(a,b))(pair_(c,d)); So I agree that it is logical to have csv() paired with list_of(), but it's only feasible for a subset of the interface of list_of(), which is (at least) just as well provided by cref_list_of()/cref_csv(). Another subset of the interface is list_of(a)(b).range(v); which could not have been implemented for cref_list_of(). The closest match is cref_list_of(a)(b) && v; but in the first case, the rhs elements are copied into an internal vector. In the second case no copying takes place, it works by keeping references to the two ranges, which is potentially faster. So overall, we have two sets of functions which differ quite significantly in their interface and implementation. The question perhaps, is if we want to leave them apart or merge the desirable features into one.
On a related subject (and perhaps slightly beyond the scope of a mini-review), have you considered a perfect forwarding version of any of these functions? Or even move-enabling the by-value ones? You're
My guess, here, is that you would like to see ref_csv() and cref_list() merged into one function that takes either of lvalues or rvalues. Is my interpretation correct?
already justifying the _ref versions on grounds of speed; this would be the logical next step in that direction. Personally I would be happy to have such only in C++0x and not bother with move-emulation in C++03, but then I don't program in C++03 any more if I can possibly help it :).
John Bytheway
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

My guess, here, is that you would like to see ref_csv() and cref_list() merged into one function that takes either of lvalues or rvalues. Is my
I meant ref_list_of(T&) and cref_list_of(const T&) merged into one, something like this? template<typename T> Implementation-defined ref_list_of(T&&);

On 16/06/10 16:55, er wrote:
My guess, here, is that you would like to see ref_csv() and cref_list() merged into one function that takes either of lvalues or rvalues. Is my
I meant ref_list_of(T&) and cref_list_of(const T&) merged into one, something like this?
template<typename T> Implementation-defined ref_list_of(T&&);
Indeed, and perhaps: template<typename... T> Implementation-defined ref_csv(T&&...) (there's some wobbles there about how to go from this list of potentially-different Ts to the one true T of the container, but they're not insurmountable) John Bytheway

template<typename... T> Implementation-defined ref_csv(T&&...)
On second thought, this does not obviate the need for cref_csv (emphasis on prefix 'c'), to express intent to cast all arguments to const, would it?.
(there's some wobbles there about how to go from this list of potentially-different Ts to the one true T of the container, but they're not insurmountable)
Do you mean int a; long b; ref_csv_0x(a,b) as potentially a problem? So it would for ref_csv, which can be solved like this: cref_csv<long>(a,b); Would not the same apply to ref_csv_0x? I'm not much familiar with 0x but I'll probably toy with these ideas (I have to emulate another OS which tells me that perhaps it's not yet mainstream) and I'll update this thread if anything meaningful comes out of it.
John Bytheway
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 19/06/10 15:50, er wrote:
template<typename... T> Implementation-defined ref_csv(T&&...)
On second thought, this does not obviate the need for cref_csv (emphasis on prefix 'c'), to express intent to cast all arguments to const, would it?.
No, although I suspect that use case is small.
(there's some wobbles there about how to go from this list of potentially-different Ts to the one true T of the container, but they're not insurmountable)
Do you mean int a; long b; ref_csv_0x(a,b) as potentially a problem? So it would for ref_csv, which can be solved like this: cref_csv<long>(a,b); Would not the same apply to ref_csv_0x?
Surprisingly it compiles, but it doesn't do what you want. It captures the first argument as an rvalue-reference instead of an lvalue-reference. This works: ref_csv_0x<long&>(a,b) but even this only 'by luck'. This for example wouldn't do what you mean: ref_csv_0x<long&>(b,a) You'd need to say ref_csv_0x<long&, long&>(b,a)
I'm not much familiar with 0x but I'll probably toy with these ideas (I have to emulate another OS which tells me that perhaps it's not yet mainstream) and I'll update this thread if anything meaningful comes out of it.
OK. John Bytheway

On 16/06/10 16:45, er wrote:
John Bytheway wrote:
I guess it wouldn't be an insurmountable task to overload csv() on the number of arguments, internally calling list_of(), and returning its
That sounds sensible. I think there should be such a function.
OK, will take that into consideration but more about that below. Meanwhile, it's already possible to do
std::vector<int> vec = (list_of(1),2,3);
That's nice to know (if not really elegant), and FWIW I certainly didn't pick it up from the docs.
What is complicating things, however, is that list_of() itself is overloaded on the number of arguments. list_of<T>(x,y)(z,w) creates an anonymous list of elements created like this : T(x,y) and T(z,w).
If you want to achieve the same thing with cref_csv, you have to do: cref_csv(T(x,y),T(z,w))
I don't understand why that is a complication. In this case it would be logical for the user to use list_of instead (at least from the perspective of amount of typing).
I would tend to always use cref_list_of(a)(b)(c) rather than list_of(a)(b)(c), because the first one is generally faster, see
https://svn.boost.org/svn/boost/sandbox/statistics/support/libs/assign/doc/s...
https://svn.boost.org/svn/boost/sandbox/statistics/support/libs/assign/doc/s...
Wow, those differences are far more dramatic than I would have expected; it looks like more than ten thousand fold in some cases! I may have to look at the code to understand this better...
and offers a more comprehensive interface such as indexing (operator[]). The function list_of() shines, however, in other areas, such as being able to call
typedef std::pair<const k_type,t_type> pair_; map = list_of<pair_>(a,b)(c,d);
(by the way this is how map_list_of(a,b)(c,d) is implemented) whereas the alternative calls for more typing:
map = cref_list_of(pair_(a,b))(pair_(c,d));
So I agree that it is logical to have csv() paired with list_of(), but it's only feasible for a subset of the interface of list_of(), which is (at least) just as well provided by cref_list_of()/cref_csv().
Another subset of the interface is
list_of(a)(b).range(v);
which could not have been implemented for cref_list_of(). The closest match is
cref_list_of(a)(b) && v;
but in the first case, the rhs elements are copied into an internal vector. In the second case no copying takes place, it works by keeping references to the two ranges, which is potentially faster.
There are clearly a lot more subtleties here than I appreciated. The impression I got from the docs seems different from the one I'm now getting from you; the docs make heavy use of list_of where you seem to be advising against it. Perhaps I'm extrapolating too much from the tutorial, and should have read the reference in more detail...
So overall, we have two sets of functions which differ quite significantly in their interface and implementation. The question perhaps, is if we want to leave them apart or merge the desirable features into one.
I'm not sure which two sets you're referring to. Is it the *ref* ones on the one hand and list_of on the other? John Bytheway

So overall, we have two sets of functions which differ quite significantly in their interface and implementation. The question perhaps, is if we want to leave them apart or merge the desirable features into one.
I'm not sure which two sets you're referring to. Is it the *ref* ones on the one hand and list_of on the other?
John Bytheway
list_of(x),y ---> cref_csv(x,y) list_of(x)(y) ---> cref_csv(x,y) list_of(x).range( v ) ---> cref_csv(x) && v; For this group of functionalities cref_csv is probably preferable, in which case the value added of a hypothetical csv that forwards to list_of() is small. list_of() ---> cref_csv(T()) list_of(x,y) ---> cref_csv(T(x,y)) list_of(x).repeat(n,y) ---> NA list_of(x).repeat(n,fun) ---> NA For theses 2 groups of functions, list_of() has some advantage in terms of reduced typing or simply cannot be replicated by the cref_xxx family of functions. Conversion and range comparison capabilities are almost the same. The difference is that it's possible to do say cref_csv(a,b) != cref_csv(c,d), not list_of(a)(b) != list_of(c)(d) but, if deemed necessary, it can be envisaged.

list_of(x).repeat(n,y) ---> NA
A compile time analog, for what it's worth, would work like this: int a = 4; BOOST_AUTO( tmp, repeat<3>(a) ); // internally calls ref_csv(a,a,a) BOOST_ASSERT( tmp[0] == 4 ); BOOST_ASSERT( tmp[1] == 4 ); BOOST_ASSERT( tmp[2] == 4 ); BOOST_ASSERT( tmp.size() == 3 ); tmp[0] = 1; BOOST_ASSERT( a == 1 ); tmp[1] = 2; BOOST_ASSERT( a == 2 ); tmp[2] = 3; BOOST_ASSERT( a == 3 ); It would be fairly to implement. I started here: http://svn.boost.org/svn/boost/sandbox/statistics/support/boost/assign/auto_...

I guess it wouldn't be an insurmountable task to overload csv() on the number of arguments, internally calling list_of(), and returning its results. That's approximately how ref_csv() and ref_list_of() relate to each other.
That sounds sensible. I think there should be such a function.
Tentatively I made the change here: http://svn.boost.org/svn/boost/sandbox/statistics/support/boost/assign/list_... Here's an example: { int a = 1, b = 2 ,c = 3; std::vector<int> vec = list_of(a).csv(b,c); BOOST_ASSERT( vec[0] == 1 ); BOOST_ASSERT( vec[1] == 2 ); BOOST_ASSERT( vec[2] == 3 ); } which can be found here http://svn.boost.org/svn/boost/sandbox/statistics/support/libs/assign/exampl... Note that list_of(a).csv(b,c), as opposed to csv(a,b,c), has the advantage of returning a reference. There is a separate thread on how to create an empty list, which would allow something like empty_list_of().csv(a,b,c), which would be more elegant.
participants (4)
-
Christopher Jefferson
-
er
-
John Bytheway
-
Thorsten Ottosen