[Review] Reminder: Boost.RangeEx review is going on
Dear Developers and Users, The review of Neil Groves' RangeEx library lasts until March 3, 2009. Please find the time to do a review if you are interested in this library. The discussion so far may be found here: http://archives.free.net.ph/message/20090220.122836.73bdbd04.en.html Below you will find a description of the library and information on how to write a review. best regards Thorsten, review manager What is it? +++++++++++ The library provide two very useful extensions to the range library 1. Range-based algorithms. E.g. boost::sort( rng ); which is a convenient wrapper of instead of std::sort( boost::begin(rng), boost::end(rng) ); But the new interface also allows for more expressive code because (on the fly) composition of algorithms suddenly is possible. 2. Range adaptors. E.g. std::vector<int> vec = ...; boost::copy( vec | boost::adaptors::reversed, std::ostream_iterator<int>( std::cout ) ); where the expression "vec | boost::adaptors::reversed" wraps the iterators of the range on the left in reverse iterators. The library provides a wide range (no pun intended) of Range adaptors, and they are a powerful way to create ranges on the fly and pass them to algorithms. Getting the library +++++++++++++++++++ The library may be downloaded from http://www.cs.aau.dk/~nesotto/boost/range_ex.zip or from the Boost vault under "Algorithms". The docs may be browsed online here http://www.cs.aau.dk/~nesotto/boost/libs/range/ Please note that the documentation is integrated with the current Range ilbrary. Therefore the relevant sections for the review is http://www.cs.aau.dk/~nesotto/boost/libs/range/doc/adaptors.html and http://www.cs.aau.dk/~nesotto/boost/libs/range/doc/algorithms.html The code may be browsed here: http://www.cs.aau.dk/~nesotto/boost/boost/range/ Notice the library is header only (exception: the adaptor tokenized() depends on Boost.Regex). Writing a review ++++++++++++++++ If you feel this is an interesting library, then please submit your review to the developer list (preferably), or to the review manager. Here are some questions you might want to answer in your review: - What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With what compiler? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick - reading? In-depth study? - Are you knowledgeable about the problem domain? And finally, every review should answer this question: - Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion. Special considerations ++++++++++++++++++++++ Various RangeEx like libraries have been implemented in the past. You might want to compare with those libraries when you form your oppinion: 1. John Torjo's range lib http://rangelib.synesis.com.au/libs/boost-rangelib-20040913.zip http://torjo.com/rangelib/index.html 2. Adobe's ASL libraries include range-based algorithms: http://stlab.adobe.com/group__algorithm.html I'm looking forward to your review. best regards Thorsten, Review Manager
Hello to be make it easy to read a table from a database
and save the result with boost serialization (and to write back back to
the database)
I have devised a scheme to achieve C++ reflections
that allows me to set a field value and get a field
value using a string data member name.
I am using the fact that in C++ functions can take
a reference to a class instance and operate on the
class data members, where the functions have
hardcoded the datamember names.
Since those functions can be declared as static,
I simply remember the pointer to my getters and setters
in static maps associated with every class instance
So when a class instance gets created -- it updates
the static maps of getters and setters.
I do not like the fact that I have to use a mutex on the
function maps.
ANd in general wanted to ask if such approach has been implemented
in one of the boost libraries or if not ... why not
I am attaching a 'brief' of the mechanism. Thank you in advance
for any feedback.
Vlad
-------------------------------------------------------------
struct tField
{
string name;
//other DB-related attributes
//order of declaration, isnullable, otltype
}
struct reflectable
{
//returns a string name of the field
char* (*tF_get_field_name)(void),
//assign a value to the field. The value is obtained from functor
//that's why we call it 'set'
typedef void (*tFset__field)(reflecatble& , CFFunctorAssignVal&) ;
//send the field value (const) to somewhere
//that's why we call it 'get'
typedef void (*tFget__field)(const reflectable&,CFFunctorReceiveVal&)
;
typedef map
Hi, I think you have the right idea. I'm also interested in this. Some quick googling brought up: http://boost-extension.redshoelace.com/docs/boost/extension/boost_extension/... but not before I had written the attached which looks like Qt's object system. The main difference between yours is that the metadata is initialized statically (or so I think!) This would get rid of that pesky mutex you have. Would be nice for Boost to have reflection capabilities but it is quite complicated to cover the whole C++ language (which is why Qt's has so many limitations.) V S P wrote:
Hello to be make it easy to read a table from a database and save the result with boost serialization (and to write back back to the database)
I have devised a scheme to achieve C++ reflections that allows me to set a field value and get a field value using a string data member name.
I am using the fact that in C++ functions can take a reference to a class instance and operate on the class data members, where the functions have hardcoded the datamember names. Since those functions can be declared as static, I simply remember the pointer to my getters and setters in static maps associated with every class instance
So when a class instance gets created -- it updates the static maps of getters and setters. I do not like the fact that I have to use a mutex on the function maps.
ANd in general wanted to ask if such approach has been implemented in one of the boost libraries or if not ... why not
I am attaching a 'brief' of the mechanism. Thank you in advance for any feedback.
Vlad -------------------------------------------------------------
struct tField { string name; //other DB-related attributes //order of declaration, isnullable, otltype }
struct reflectable {
//returns a string name of the field char* (*tF_get_field_name)(void),
//assign a value to the field. The value is obtained from functor //that's why we call it 'set' typedef void (*tFset__field)(reflecatble& , CFFunctorAssignVal&) ;
//send the field value (const) to somewhere //that's why we call it 'get' typedef void (*tFget__field)(const reflectable&,CFFunctorReceiveVal&) ;
typedef map
tName2Fields; typedef map tMFset__field; typedef map tMFget__field; //derived classes must have the "static" version of the maps //we inforce it by declaring abstract functions here //also each class will have to provide a static function //that gets returns a pointer to each map };
tempate < typename T, //cpp type tF_get_field_name fname, //function ptr to get name tFset__field assing_functor, //functor pointer to assing val to field tFget__field get_functor, //functor to read val from field
tName2Fields* ptrFieldMap, tMFset__field* ptrSetterMap, tFget__field* ptrGetterMap
struct rffield { //register a field name (obtained from fname() //with ptrFieldMap
//register pointer to getter with ptrGetterMap //register pointer to setter with ptrSetMap
}
---- separate header -----------------
struct myclass: public reflecatble { static allTheMaps...;
//to simplify I have a macro that takes in field name, cpp type //and declares them and generates getter and setter functions //that accept functors
static void field1__getter ( const reflectable&th,CFFunctorReceiveVal& f) { f(th.field1); } static void field1__setter ( const reflectable& th,CFFunctorAssignVal& f) { f(th.field1); }
static const char* field1__name (void) { const char* res="field1"; return res; }
//single declration causes all the registration to take place //since I am passing parameteres to rffield constructor //via template. It is almost like ability to invoke constructor // right in a header file. rffield
field1; }
------------ cpp for my class has the static maps -- -----------
-- Sohail Somani http://uint32t.blogspot.com
Sohail Somani wrote:
Hi,
I think you have the right idea. I'm also interested in this. Some quick googling brought up: [snip lots of stuff]
PS: Sorry for the double whammy of top posting and over quoting :-) -- Sohail Somani http://uint32t.blogspot.com
Hello all,
Hello to be make it easy to read a table from a database and save the result with boost serialization (and to write back back to the database)
I have such as system working, including an odbc c++ wrapper. I've been developing this since 2004, unfortunately have not had much time to do some proper "marketing". I've just restarted public development. Here are some relevant links: Entry point for the whole endevour: http://www.litwindow.com/Library/index.html This is a description of the 'reflection' mechanism. http://www.litwindow.com/Library/Articles/dataabstractionlayer.htm Basically my code looks like this: struct Foo { SomeClass m_myaggregate; int m_basic_datatype; vector<SomeOtherClass> m_myvector; }; The reflection definition requires this: LWL_BEGIN_AGGREGATE(Foo) PROP(m_myaggregate) PROP(m_basic_datatype) PROP(m_myvector) LWL_END_AGGREGATE() and currently you will also need a LWL_IMPLEMENT_CONTAINER(vector<SomeOtherClass>) Once you've written this, you can then Foo myFoo; litwindow::aggregate ag=make_aggregate(myFoo); litwindow::aggregate::iterator i; for (i=ag.begin(); i!=ag.end(); ++i) { if (i->is_container()==false) { printf("Member %s=%s", i->name(), i->to_string()); } else { // print contents of a container } } IOW use an iterator to iterate over the members of an aggregate. The ODBC library allows Foo myFoo; odbc::table t("MyTable", m_odbc_connection); t.bind(myFoo); // bind all members to columns of the same name in the table "MyTable" and then deal with the table. This is the sourceforge project: http://sourceforge.net/projects/litwindow I am interested in boostifying this more than it currently is and perhaps, if there is enough interest and perhaps some help from the community in crossplatforming this, fixing the documentation enough so that it might actually be reviewed at one time. BTW, the current version in sourceforge also includes a C++ library wrapper for ODBC, which is not yet mentioned in the documentation. The build system is using boost.build now, although the code has only been tested on Windows platform using Visual Studio compilers. Best regards Hajo -- Hajo Kirchhoff Kirchhoff IT-Consulting Hilpertstr 13 91052 Erlangen Germany http://www.litwindow.com Phone: ++49 9131 209272
I'm thinking right now about such a thing too. I decided to use soci, as it is a really good SQL Lib for C++: soci.sourceforge.net My current approach is from the DB side, I'm writing a programm which generates classes from CREATE TABLE statements. I think by next weekend I got a prototype ready. regards, Jens Weller -------- Original-Nachricht --------
Datum: Sat, 28 Feb 2009 11:21:50 -0500 Von: "V S P"
An: boost-users@lists.boost.org Betreff: [Boost-users] [Q] opinion on basic C++ reflection implementation
Hello to be make it easy to read a table from a database and save the result with boost serialization (and to write back back to the database)
I have devised a scheme to achieve C++ reflections that allows me to set a field value and get a field value using a string data member name.
I am using the fact that in C++ functions can take a reference to a class instance and operate on the class data members, where the functions have hardcoded the datamember names. Since those functions can be declared as static, I simply remember the pointer to my getters and setters in static maps associated with every class instance
So when a class instance gets created -- it updates the static maps of getters and setters. I do not like the fact that I have to use a mutex on the function maps.
ANd in general wanted to ask if such approach has been implemented in one of the boost libraries or if not ... why not
I am attaching a 'brief' of the mechanism. Thank you in advance for any feedback.
Vlad -------------------------------------------------------------
struct tField { string name; //other DB-related attributes //order of declaration, isnullable, otltype }
struct reflectable {
//returns a string name of the field char* (*tF_get_field_name)(void),
//assign a value to the field. The value is obtained from functor //that's why we call it 'set' typedef void (*tFset__field)(reflecatble& , CFFunctorAssignVal&) ;
//send the field value (const) to somewhere //that's why we call it 'get' typedef void (*tFget__field)(const reflectable&,CFFunctorReceiveVal&) ;
typedef map
tName2Fields; typedef map tMFset__field; typedef map tMFget__field; //derived classes must have the "static" version of the maps //we inforce it by declaring abstract functions here //also each class will have to provide a static function //that gets returns a pointer to each map };
tempate < typename T, //cpp type tF_get_field_name fname, //function ptr to get name tFset__field assing_functor, //functor pointer to assing val to field tFget__field get_functor, //functor to read val from field
tName2Fields* ptrFieldMap, tMFset__field* ptrSetterMap, tFget__field* ptrGetterMap
struct rffield { //register a field name (obtained from fname() //with ptrFieldMap
//register pointer to getter with ptrGetterMap //register pointer to setter with ptrSetMap
}
---- separate header -----------------
struct myclass: public reflecatble { static allTheMaps...;
//to simplify I have a macro that takes in field name, cpp type //and declares them and generates getter and setter functions //that accept functors
static void field1__getter ( const reflectable&th,CFFunctorReceiveVal& f) { f(th.field1); } static void field1__setter ( const reflectable& th,CFFunctorAssignVal& f) { f(th.field1); }
static const char* field1__name (void) { const char* res="field1"; return res; }
//single declration causes all the registration to take place //since I am passing parameteres to rffield constructor //via template. It is almost like ability to invoke constructor // right in a header file. rffield
field1; }
------------ cpp for my class has the static maps -- ----------- -- V S P toreason@fastmail.fm
-- http://www.fastmail.fm - Faster than the air-speed velocity of an unladen european swallow
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger01
On Sun, Mar 1, 2009 at 6:44 PM, Jens Weller
I'm thinking right now about such a thing too. I decided to use soci, as it is a really good SQL Lib for C++: soci.sourceforge.net
I don't use DBs on C++ anymore. Back in the days I did, SOCI was by far our best choice. Three years have passed and I believe it has evolved and even other solutions may exist. But definitely it was the best back then. My 1E-2 cents, Madera
Some issues:
1.
This fails to compile:
#include
What is your evaluation of the design? Good design.
What is your evaluation of the documentation? It has some issues mentioned above.
What is your evaluation of the potential usefulness of the library? Very useful. Will reduce a lot of boilerplate code. In particular, it provides the most elegant solution of "for-each-value-in-a-map" problem. I have not used old Range library, because I have not found it that useful.
Did you try to use the library? With what compiler? Did you have any problems? MSVC8, the problem described above. Without Boost.Thread included before Boost.Range it seems to work. Maybe tomorrow (March 2nd) will try on production code.
How much effort did you put into your evaluation? A glance? A quick - reading? In-depth study? A quick reading.
Are you knowledgeable about the problem domain? Been writing production code in C++ for 2 years, using STL and Boost a lot. Work in a project where all STL containers and most of STL algorithms are used, also used Boost.Iterators and Boost.Foreach. I have not used Boost.Range before, beause have not found it much useful.
Do you think the library should be accepted as a Boost library? Yes.
If you feel this is an interesting library, then please submit your review to the developer list (preferably), or to the review manager.
I'm not a member of the developer list, so I'm sending this to the Boost.User's list and Thorsten Ottosen. Hope that's ok.
Here are some questions you might want to answer in your review:
- What is your evaluation of the design?
I really like it. It's feels very expressive. I wish something like this was available a long time ago.
- What is your evaluation of the implementation?
I didn't look into the source code.
- What is your evaluation of the documentation?
Found some very small mistakes in http://www.cs.aau.dk/~nesotto/boost/libs/range/doc/adaptors.html. 1) "where added to be equivalent" should be "were added to be equivalent". 2) "The answer is readbility" should be "The answer is readability". 3) code snippet where the virtues of using operator |() are extolled shows "boost::adaptors::unique" but it should be "boost::adaptors::uniqued". 4) "satisfies that predicated" should be "satisfies that predicate".
- What is your evaluation of the potential usefulness of the library?
I think it'll be very useful and will make code more readable. Rather than fiddling with the boundaries of ranges, you can just use the range. If a function returns a STL-compliant container which I need to do something with, I currently have a const& to the returned container, then do something with its begin() and end(). Now I can just get on and do whatever I need to do directly on the return value.
- Did you try to use the library? With what compiler? Did you have any problems?
I did. I used Microsoft Visual Studio 7.1 (2003 with SP1) and Boost 1.38.0.
I went through the most of the adaptors and tried out the examples.
Didn't really understand the difference between the adaptors "copied"
and "sliced". Is there any?
I took the example on the replaced adaptors page
(http://www.cs.aau.dk/~nesotto/boost/libs/range/doc/adaptors/replaced.html)
and modified it for std::string. It failed to compile on MSVC7.1
(2003). Here's the code:
#include
- How much effort did you put into your evaluation? A glance? A quick - reading? In-depth study?
It was a quick-reading.
- Are you knowledgeable about the problem domain?
Fairly. I've been using STL containers and algorithms for over 5 years.
And finally, every review should answer this question:
- Do you think the library should be accepted as a Boost library?
Yes.
Peter Barker skrev:
If you feel this is an interesting library, then please submit your review to the developer list (preferably), or to the review manager.
I'm not a member of the developer list, so I'm sending this to the Boost.User's list and Thorsten Ottosen. Hope that's ok.
That is perfectly fine. -Thorsten
participants (8)
-
Alexander
-
Hajo Kirchhoff
-
Jens Weller
-
Peter Barker
-
Rodrigo Madera
-
Sohail Somani
-
Thorsten Ottosen
-
V S P