Re: [Boost-users] [review][assign] Formal review of Assign v2 ongoing
This was posted to lib.boost.devel, but I meant to post it in boost.user as well:
About your other comments: - operator| has a similar meaning in Boost.Range under adaptors. - Feel free to suggest another prefix than 'do'. - Dot is borrowed from Boost.Assign (1.0).
Did you mean dot or %? The dot is a small price to pay for alternating
between various ways to insert elements in a container, within one
statement:
put( cont )( x, y, z ).for_each( range1 )( a, b ).for_each( range2 );
The answer to "[Is it] just a quest to type less when using standard
containers?" is yes, as illustrated just above, but it is quite a broad
definition of standard containers. Version 2.0 provides macros to
broaden it further (which was used to support Boost.MultiArray, for
example).
As for why such a library should exist, it depends on the degree to
which you value the syntax above, which is very similar to Boost.Assign
(1.0), in this case.
You say "I ordinarily only initialize containers to literals when
writing unit tests.". In this case, I think you are right that you can't
beat C++0x initializer lists. But, you still may need to fill a
container, as above. And also, consider the cases below:
#include <vector>
#include <queue>
#include <string>
#include <tuple>
#include
- Prefix _ is reserved for const objects (not sure the proper word for it)
And I think this convention appears elsewhere in Boost, such as Boost.Parameter. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
er wrote:
You say "I ordinarily only initialize containers to literals when writing unit tests.". In this case, I think you are right that you can't beat C++0x initializer lists. But, you still may need to fill a container, as above. And also, consider the cases below:
#include <vector> #include <queue> #include <string> #include <tuple> #include
int main() { typedef std::string s_; { typedef std::tuple
t_; typedef std::vector v_; v_ v1 = { t_( "a", 1 ), t_( "b", 2 ), t_( "c", 3 ), t_( "d", 4 ), t_( "e", 5 ) }; using namespace boost::assign::v2; v_ v2 = converter( csv_deque ( "a", 1, "b", 2, "c", 3, "d", 4, "e", 5) ); }
No, initializer lists can apply to the elements and be nested. v_ v1 = { { "a", 1 }, { "b", 2 }, { "c", 3 }, { "d", 4 }, { "e", 5 } }; Arguably the extra {} around each vector element in the new initializer syntax is more readable than the proposed assign v2 syntax. Tuple and deque support initializer list as do all classes with constructors and structs. I would like to know if there will be a boost.parameter v2 that works with initializer lists and default values of struct members. struct S { int a; int b = 1; int c = 2; } S s1 = {0, 1, 2}; S s2 = {0}; //use default b and c S s3 = {0, 1}; //use default c S s4 = {0, c = 2}; //use default b That would be very nice, but I don't know if we can accomplish it. Regards, Luke
Arguably the extra {} around each vector element in the new initializer syntax is more readable than the proposed assign v2 syntax. Tuple and deque support initializer list as do all classes with constructors and structs.
I have to believe that you are right in principle, because I'm not too well versed in intialization lists, and thanks for spotting it. But few compilers already fully support C++0x. In the case of gcc4.4 that I use, which has proven C++0x conformant until now, I get the compiler error "converting from initializer list would use explicit constructor".
er wrote:
Arguably the extra {} around each vector element in the new initializer syntax is more readable than the proposed assign v2 syntax. Tuple and deque support initializer list as do all classes with constructors and structs.
I have to believe that you are right in principle, because I'm not too well versed in intialization lists, and thanks for spotting it. But few compilers already fully support C++0x. In the case of gcc4.4 that I use, which has proven C++0x conformant until now, I get the compiler error "converting from initializer list would use explicit constructor".
If it is true that you cannot use an initializer list with an explicit constructor in the new standard I think it will make explict constructors very painful. I may not have reasoned it through fully, but I see no reason not to allow initializer lists to use explict constructors. It doesn't seem to create safety concerns or ambiguity. Does someone know the rationale for that? It seems to be a mistake to me. Regards, Luke
If it is true that you cannot use an initializer list with an explicit constructor in the new standard I think it will make explict constructors very painful. I may not have reasoned it through fully, but I see no reason not to allow initializer lists to use explict constructors. It doesn't seem to create safety concerns or ambiguity. Does someone know the rationale for that? It seems to be a mistake to me.
I'm only reporting what I observe, and I'm unable to make a judgment. Hopefully someone with a later version of gcc can confirm or infirm. In any case, it still leaves containers that have not been augmented with initializer list constructors, such as queue, for which Assign is helpful under C++0x, for the task of initializing a container. Thanks for sharing your thoughts.
Regards, Luke
On 6/21/11 7:08 PM, er wrote:
If it is true that you cannot use an initializer list with an explicit constructor in the new standard I think it will make explict constructors very painful. I may not have reasoned it through fully, but I see no reason not to allow initializer lists to use explict constructors. It doesn't seem to create safety concerns or ambiguity. Does someone know the rationale for that? It seems to be a mistake to me.
I'm only reporting what I observe, and I'm unable to make a judgment. Hopefully someone with a later version of gcc can confirm or infirm.
In any case, it still leaves containers that have not been augmented with initializer list constructors, such as queue, for which Assign is helpful under C++0x, for the task of initializing a container.
Thanks for sharing your thoughts.
Regards, Luke
Did you get a chance to think it through? It would be nice to clarify this issue before the review closes, tomorrow. PS: This thread stopped but still continues in lib.boost.devel. Here's a copy of my last post hoping it makes the purpose of v2 more clear.
I think your library needs to do better than coming up with a slightly different syntax than V1, otherwise I don't see the point of having it.
Indeed, but I claim more than a slightly different syntax. The
fixed-arity stuff is quite a different syntax. The other stated goals of
the design, in the change-log, are, amongst other things, to bring these
improvements:
1- Code reuse because deque and put share the same crtp
2- Code decoupling (modularity)
3- Open for extension (albeit not enough, see my response to)
Do I have to argue that these objectives worthwhile?! No, so I please
ask whether they are were met, and if not, what is lacking. PS: maybe I
did not state 3-.
Let's assume I get paid for writing a TPS report, every day, involving
100 unit-tests such as the one below.
STL approach:
std::deque<int> cont;
const int n = 2;
int x = log10( 1 );
for(int i = 0; i < n; i++)
{
cont.push_front( x );
}
x = log10( 10 );
for(int i = 0; i < n; i++)
{
cont.push_front( x );
}
x = log10( 100 );
for(int i = 0; i < n; i++)
{
cont.push_front( x );
}
x = log10( 1000 );
for(int i = 0; i < n; i++)
{
cont.push_front( x );
}
assert(
boost::range::equal(
cont,
csv_deque( 3, 3, 2, 2, 1, 1, 0, 0 )
)
);
PS: No need to argue that a nested loop would made the job easier. Your
boss can make it as arcane as he likes and he might have as well
re-arranged 1, 10, 100, 1000 in a different order.
Assign 2.0:
BOOST_AUTO( _r, ( _repeat = 2 ) );
typedef function
er wrote:
On 6/21/11 7:08 PM, er wrote:
If it is true that you cannot use an initializer list with an explicit constructor in the new standard I think it will make explict constructors very painful. I may not have reasoned it through fully, but I see no reason not to allow initializer lists to use explict constructors. It doesn't seem to create safety concerns or ambiguity. Does someone know the rationale for that? It seems to be a mistake to me.
I'm only reporting what I observe, and I'm unable to make a judgment. Hopefully someone with a later version of gcc can confirm or infirm.
In any case, it still leaves containers that have not been augmented with initializer list constructors, such as queue, for which Assign is helpful under C++0x, for the task of initializing a container.
Thanks for sharing your thoughts.
Regards, Luke
Did you get a chance to think it through? It would be nice to clarify this issue before the review closes, tomorrow.
Oh, I thought you were trying to close the thread when you finished with "Thanks for sharing your thoughts."
PS: This thread stopped but still continues in lib.boost.devel. Here's a copy of my last post hoping it makes the purpose of v2 more clear.
I've been following it closely. I came to the point where the motivation for using the library appeared to boil down to "initializer lists in C++ are broken, therefore we need a library solution." I don't know if they are broken, or how broken they are, or if they will or can be fixed. I do know that the fact that compilers don't *currently* support them is no good reason for a library. Boost.Assign should be obsolete with C++0x initializer lists. If that isn't the case then I would argue that initializer lists are broken in the standard. I use initializer lists every day in another langauge and they are really great. If we had to compromise between old and busted in C++98 and new hottness that we could get writing a language from scratch and got initializer list langauge features that fall somewhere between then that will be a bitter dissapointment for me. I was hoping someone could clarify just how broken or not-broken initializer lists are in the standard. Apparently containers have to explicitly declare an initializer list constructor. That's bad, but as long as every std container does so I can live with it. What about PODs? What about structs? What about default values of constructor arguments? What about explicit constructors? How are auto casting handled? Does initializer list have to be an exact match for the argument type? Does that result in function call ambiguity when trying to pass initializer lists? There are a lot of issues that I don't have time to dig into. In the end, dissapointment in the new standard isn't a strong position from which to motivate me to use the library. I probably wouldn't use assign V1, but at least I find code that does use it readable. The V2 syntax is unintelligable without reading the documentation. Conciseness at the expense of readability is a horrible trade off. Even if I wouldn't use a library myself, I would approve of it if I would approve of other people using it. To each his own. But a library that I object to other people using becaues I never want to come into contact with their code is another story. First impression and subsequent discussion leads me to conclude that I never want to come into contact with code written the V2 syntax. I much prefer the V1 syntax (even if I wouldn't actually use it) and I don't see the benefit of V2 over V1 or even V2 over vanilla C++ standard practice, even leaving aside C++0x initializer lists. I was trying to be merciful by not jumping onto the pile... Regards, Luke
Oh, I thought you were trying to close the thread when you finished with "Thanks for sharing your thoughts."
PS: This thread stopped but still continues in lib.boost.devel. Here's a copy of my last post hoping it makes the purpose of v2 more clear.
I've been following it closely.
That's nice to know, thanks.
I came to the point where the motivation for using the library appeared to boil down to "initializer lists in C++ are broken, therefore we need a library solution." I don't know if they are broken, or how broken they are, or if they will or can be fixed. I do know that the fact that compilers don't *currently* support them is no good reason for a library. Boost.Assign should be obsolete with C++0x initializer lists. If that isn't the case then I would argue that initializer lists are broken in the standard. I use initializer lists every day in another langauge and they are really great. If we had to compromise between old and busted in C++98 and new hottness that we could get writing a language from scratch and got initializer list langauge features that fall somewhere between then t hat will be a bitter dissapointment for me. I was hoping someone could clarify just how broken or not-broken initializer lists are in the standard. Apparently containers have to explicitly declare an initializer list constructor. That's bad, but as long as every std container does so I can live with it. What about PODs? What about structs? What about default values of constructor arguments? What about explicit constructors? How are auto casting handled? Does initializer list have to be an exact match for the argument type? Does that result in function call ambiguity when trying to pass initializer lists? There are a lot of issues that I don't have time to dig into.
I have a feeling all these open questions are about C++0x, not V2, right?
I was trying to be merciful by not jumping onto the pile...
Generational gap, I suppose.
Regards, Luke
On 21/06/11 23:05, Simonson, Lucanus J wrote:
er wrote:
You say "I ordinarily only initialize containers to literals when writing unit tests.". In this case, I think you are right that you can't beat C++0x initializer lists. But, you still may need to fill a container, as above. And also, consider the cases below:
#include <vector> #include <queue> #include <string> #include <tuple> #include
int main() { typedef std::string s_; { typedef std::tuple
t_; typedef std::vector v_; v_ v1 = { t_( "a", 1 ), t_( "b", 2 ), t_( "c", 3 ), t_( "d", 4 ), t_( "e", 5 ) }; using namespace boost::assign::v2; v_ v2 = converter( csv_deque ( "a", 1, "b", 2, "c", 3, "d", 4, "e", 5) ); } No, initializer lists can apply to the elements and be nested.
v_ v1 = { { "a", 1 }, { "b", 2 }, { "c", 3 }, { "d", 4 }, { "e", 5 } };
Arguably the extra {} around each vector element in the new initializer syntax is more readable than the proposed assign v2 syntax. Tuple and deque support initializer list as do all classes with constructors and structs.
For what it's worth, your particular example doesn't work in gcc 4.5 because the relevant constructor of std::tuple's is explicit (I wasn't aware of this effect of marking a constructor explicit, and I'm quite surprised...). The analogous example with std::pair works fine. John Bytheway
AMDG On 06/23/2011 03:45 PM, John Bytheway wrote:
On 21/06/11 23:05, Simonson, Lucanus J wrote:
v_ v1 = { { "a", 1 }, { "b", 2 }, { "c", 3 }, { "d", 4 }, { "e", 5 } };
Arguably the extra {} around each vector element in the new initializer syntax is more readable than the proposed assign v2 syntax. Tuple and deque support initializer list as do all classes with constructors and structs.
For what it's worth, your particular example doesn't work in gcc 4.5 because the relevant constructor of std::tuple's is explicit (I wasn't aware of this effect of marking a constructor explicit, and I'm quite surprised...). The analogous example with std::pair works fine.
Yep. You have to use v_ v1{ { "a", 1 }, { "b", 2 }, { "c", 3 }, { "d", 4 }, { "e", 5 }, }; In Christ, Steven Watanabe
On 24/06/11 03:17, Steven Watanabe wrote:
AMDG
On 06/23/2011 03:45 PM, John Bytheway wrote:
On 21/06/11 23:05, Simonson, Lucanus J wrote:
v_ v1 = { { "a", 1 }, { "b", 2 }, { "c", 3 }, { "d", 4 }, { "e", 5 } };
Arguably the extra {} around each vector element in the new initializer syntax is more readable than the proposed assign v2 syntax. Tuple and deque support initializer list as do all classes with constructors and structs.
For what it's worth, your particular example doesn't work in gcc 4.5 because the relevant constructor of std::tuple's is explicit (I wasn't aware of this effect of marking a constructor explicit, and I'm quite surprised...). The analogous example with std::pair works fine.
Yep. You have to use
v_ v1{ { "a", 1 }, { "b", 2 }, { "c", 3 }, { "d", 4 }, { "e", 5 }, };
That doesn't work in gcc 4.5 either; I get the same error about use of an explicit constructor. John
participants (4)
-
er
-
John Bytheway
-
Simonson, Lucanus J
-
Steven Watanabe