Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53023 - in sandbox/mirror: boost/mirror libs/mirror/example/factories
From: chochlik_at_[hidden]
Date: 2009-05-15 05:24:52


Author: matus.chochlik
Date: 2009-05-15 05:24:50 EDT (Fri, 15 May 2009)
New Revision: 53023
URL: http://svn.boost.org/trac/boost/changeset/53023

Log:
[mirror 0.4.x]
- added constructor_caller and advanced_constructor_caller functors
  for more convenient calling of class' constructors
- updated the inserter example to show the usage of the functor callers

Added:
   sandbox/mirror/libs/mirror/example/factories/class_printer.hpp (contents, props changed)
   sandbox/mirror/libs/mirror/example/factories/yes_no_dlg.hpp (contents, props changed)
Text files modified:
   sandbox/mirror/boost/mirror/adv_func_call.hpp | 54 +++++++++
   sandbox/mirror/boost/mirror/functor_call.hpp | 40 +++++++
   sandbox/mirror/libs/mirror/example/factories/inserter.cpp | 222 +++++++++++++++++++++------------------
   3 files changed, 211 insertions(+), 105 deletions(-)

Modified: sandbox/mirror/boost/mirror/adv_func_call.hpp
==============================================================================
--- sandbox/mirror/boost/mirror/adv_func_call.hpp (original)
+++ sandbox/mirror/boost/mirror/adv_func_call.hpp 2009-05-15 05:24:50 EDT (Fri, 15 May 2009)
@@ -302,6 +302,17 @@
                 ); \
         } \
 public: \
+ template <BOOST_PP_ENUM_PARAMS(ARITY, typename T) > \
+ inline result_type operator()( \
+ BOOST_PP_ENUM_BINARY_PARAMS(ARITY, const T, & p) \
+ ) \
+ { \
+ return call( \
+ _meta_function::wrap(), \
+ BOOST_PP_ENUM_PARAMS(ARITY, p) \
+ ); \
+ } \
+ \
         template <class Class, BOOST_PP_ENUM_PARAMS(ARITY, typename T) > \
         inline result_type operator()( \
                 Class& instance, \
@@ -393,6 +404,49 @@
 };
 
 
+/** A more convenient interface for calling constructors
+ */
+template <
+ template <class> class Manufacturer,
+ class Class,
+ int FuncIndex,
+ class ParamMapping_c
+> struct advanced_constructor_caller : public advanced_functor_caller<
+ Manufacturer,
+ meta_constructors<Class>,
+ mpl::int_<FuncIndex>,
+ typename ParamMapping_c::type
+>
+{
+private:
+ typedef advanced_functor_caller<
+ Manufacturer,
+ meta_constructors<Class>,
+ mpl::int_<FuncIndex>,
+ typename ParamMapping_c::type
+ > base_class;
+public:
+ inline advanced_constructor_caller(void)
+ : base_class(0)
+ { }
+
+ template <class FactoryParam>
+ inline advanced_constructor_caller(FactoryParam factory_param)
+ : base_class(factory_param)
+ { }
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+ template <class FactoryParam, class ...Defaults>
+ inline advanced_constructor_caller(
+ FactoryParam factory_param,
+ Defaults ...defs
+ ): base_class(factory_param, defs...)
+ { }
+#endif
+};
+
+/** A more convenient interface for calling member functions
+ */
 template <
         template <class> class Manufacturer,
         class Class,

Modified: sandbox/mirror/boost/mirror/functor_call.hpp
==============================================================================
--- sandbox/mirror/boost/mirror/functor_call.hpp (original)
+++ sandbox/mirror/boost/mirror/functor_call.hpp 2009-05-15 05:24:50 EDT (Fri, 15 May 2009)
@@ -205,6 +205,46 @@
         }
 };
 
+/** A template with more cdd.onvenient interface, for calling constructors
+ * of a class
+ */
+template <
+ template <class> class Manufacturer,
+ class Class,
+ int FuncIndex
+> struct constructor_caller : public functor_caller<
+ Manufacturer,
+ meta_constructors<Class>,
+ mpl::int_<FuncIndex>
+>
+{
+private:
+ typedef functor_caller<
+ Manufacturer,
+ meta_constructors<Class>,
+ mpl::int_<FuncIndex>
+ > base_class;
+public:
+ inline constructor_caller(void)
+ : base_class(0)
+ { }
+
+ template <class FactoryParam>
+ inline constructor_caller(FactoryParam factory_param)
+ : base_class(factory_param)
+ { }
+
+#ifndef BOOST_NO_VARIADIC_TEMPLATES
+ template <class FactoryParam, class ...Defaults>
+ inline constructor_caller(
+ FactoryParam factory_param,
+ Defaults ...defs
+ ): base_class(factory_param, defs...)
+ { }
+#endif
+
+};
+
 /** A template with more convenient interface, for calling member functions
  * of a class
  */

Added: sandbox/mirror/libs/mirror/example/factories/class_printer.hpp
==============================================================================
--- (empty file)
+++ sandbox/mirror/libs/mirror/example/factories/class_printer.hpp 2009-05-15 05:24:50 EDT (Fri, 15 May 2009)
@@ -0,0 +1,64 @@
+/**
+ * \file examples/factories/class_printer.cpp
+ *
+ * This example shows how to use the generic function callers.
+ *
+ * Copyright 2008-2009 Matus Chochlik. Distributed under the Boost
+ * Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_MIRROR_EXAMPLES_FACTORIES_CLASS_PRINTER_HPP
+#define BOOST_MIRROR_EXAMPLES_FACTORIES_CLASS_PRINTER_HPP
+
+#include <boost/char_type_switch/iostream.hpp>
+#include <boost/mirror/meta_class.hpp>
+#include <boost/mirror/algorithm/for_each.hpp>
+
+/** Prints the types, names and values of
+ * class' attribute
+ */
+template <class Class>
+struct attrib_printer
+{
+ const Class& inst;
+
+ attrib_printer(const Class& _inst)
+ : inst(_inst)
+ { }
+
+ template <class MetaAttribute>
+ void operator()(MetaAttribute ma) const
+ {
+ ::boost::cts::bcout() <<
+ BOOST_CTS_LIT("\t") <<
+ MetaAttribute::type::base_name() <<
+ BOOST_CTS_LIT(" ") <<
+ MetaAttribute::base_name() <<
+ BOOST_CTS_LIT(": '") <<
+ MetaAttribute::get(inst) <<
+ BOOST_CTS_LIT("'") <<
+ ::std::endl;
+ }
+};
+
+/** Prints the type name of a class and
+ * it's attributes
+ */
+struct class_printer
+{
+ template <class Class>
+ void operator()(const Class& inst)
+ {
+ ::boost::cts::bcout() <<
+ BOOST_MIRRORED_CLASS(Class)::base_name() <<
+ ::std::endl;
+
+ ::boost::mirror::for_each<
+ typename BOOST_MIRRORED_CLASS(Class)::all_attributes
+ >(attrib_printer<Class>(inst));
+ }
+};
+
+#endif
+

Modified: sandbox/mirror/libs/mirror/example/factories/inserter.cpp
==============================================================================
--- sandbox/mirror/libs/mirror/example/factories/inserter.cpp (original)
+++ sandbox/mirror/libs/mirror/example/factories/inserter.cpp 2009-05-15 05:24:50 EDT (Fri, 15 May 2009)
@@ -1,72 +1,31 @@
 /**
  * \file examples/factories/inserter.cpp
  *
- * This example shows how to use the generic function caller.
+ * This example shows how to use the generic function callers.
  *
  * Copyright 2008 Matus Chochlik. Distributed under the Boost
  * Software License, Version 1.0. (See accompanying file
  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  */
 
-#include <math.h>
 #include <list>
-#include <algorithm>
 
 #include <boost/char_type_switch/iostream.hpp>
 
 #include <boost/mirror/adv_func_call.hpp>
-#include <boost/mirror/meta_mem_functions.hpp>
 #include <boost/mirror/meta_class.hpp>
 #include <boost/mirror/algorithm/for_each.hpp>
 
 #include "./input_ui.hpp"
+#include "./class_printer.hpp"
+#include "./yes_no_dlg.hpp"
 #include "./person.hpp"
 
-/** Prints the types, names and values of
- * class' attribute
- */
-template <class Class>
-struct attrib_printer
-{
- const Class& inst;
-
- attrib_printer(const Class& _inst)
- : inst(_inst)
- { }
-
- template <class MetaAttribute>
- void operator()(MetaAttribute ma) const
- {
- ::boost::cts::bcout() <<
- BOOST_CTS_LIT("\t") <<
- MetaAttribute::type::base_name() <<
- BOOST_CTS_LIT(" ") <<
- MetaAttribute::base_name() <<
- BOOST_CTS_LIT(": '") <<
- MetaAttribute::get(inst) <<
- BOOST_CTS_LIT("'") <<
- ::std::endl;
- }
-};
-
-/** Prints the type name of a class and
- * it's attributes
- */
-struct class_printer
+template <typename String>
+bool from_same_place(const String& a, const String& b, const String& c)
 {
- template <class Class>
- void operator()(const Class& inst)
- {
- ::boost::cts::bcout() <<
- BOOST_MIRRORED_CLASS(Class)::base_name() <<
- ::std::endl;
-
- ::boost::mirror::for_each<
- typename BOOST_MIRRORED_CLASS(Class)::all_attributes
- >(attrib_printer<Class>(inst));
- }
-};
-
+ return !(a.empty() || b.empty() || c.empty());
+}
 
 int main(void)
 {
@@ -76,77 +35,130 @@
         //
         // a list of persons
         ::std::list< person > persons;
+ bool insert_more = true;
+ //
+ cts::bstring city;
+ cts::bstring postal_code;
+ cts::bstring country;
+ //
+ if(yes_no_dlg(BOOST_CTS_LIT("Are all persons from the same city? (y/n)")))
+ {
+ cts::bcout() << BOOST_CTS_LIT("Enter city: ") << ::std::flush;
+ getline(cts::bcin(), city);
+ cts::bcout() << BOOST_CTS_LIT("Enter postal code: ") << ::std::flush;
+ getline(cts::bcin(), postal_code);
+ cts::bcout() << BOOST_CTS_LIT("Enter country: ") << ::std::flush;
+ getline(cts::bcin(), country);
+ }
         //
- const cts::bchar yes = BOOST_CTS_LIT('y');
- const cts::bchar no = BOOST_CTS_LIT('n');
- cts::bchar insert_more = yes;
- cts::bchar change_address = no;
         // keep inserting while insert_more == 'y'
- while(insert_more == yes)
+ while(insert_more)
         {
- factory<input_ui, person> fact;
- persons.push_back(fact());
- //
- // check whether to insert more persons
- do
+ // if all the persons are from the same place
+ // we can supply some of the params from the
+ // city/postal_code/country local variables
+ if(from_same_place(city, postal_code, country))
                 {
- cts::bcout() <<
- BOOST_CTS_LIT("Change persons address ? (y/n) ") <<
- ::std::flush;
- cts::bcin() >> change_address;
- cts::bcin().ignore();
- } while(change_address != yes && change_address != no);
- if(change_address == yes)
+ // use the advanced constructor caller
+ // to create a person
+ advanced_constructor_caller<
+ input_ui, // the user interface template
+ person, // the constructed class
+ 0, // the index of the constructor
+ mpl::vector_c<
+ int,//the parameter mapping
+ 0, // enter name on console
+ 0, // enter surname on console
+ 0, // enter street on console
+ 0, // enter st. number on console
+ 1, // use the 1st param as city
+ 2, // use the 2nd param as postal code
+ 3 // use the 3rd param as country
+ >
+ > fact;
+ // and push it back to the list
+ persons.push_back(fact(city, postal_code, country));
+ }
+ else
+ {
+ // use the factory to get input data from the console
+ // and to construct an instance of person
+ factory<input_ui, person> fact;
+ // and push it back to the list
+ persons.push_back(fact());
+ }
+ //
+ // ask whether the user wants to change the address
+ // of the person which we just inserted.
+ // its kinda strange to do it right after we entered
+ // the address, but we just want to show the functor_callers
+ // anyway
+ if(yes_no_dlg(BOOST_CTS_LIT("Change persons address ? (y/n) ")))
                 {
                         person& p(persons.back());
+ //
+ // if they're from the same place
+ if(from_same_place(city, postal_code, country))
+ {
+ // use the advanced member function caller
+ // so we can supply some of the pre-entered
+ // values
+ advanced_mem_func_caller<
+ input_ui, // the user interface
+ person, // the class
+ 0, // the index of the mem function
+ mpl::vector_c<
+ int, // the param mapping
+ 0,
+ 0,
+ 1,
+ 2,
+ 3
+ >
 #ifdef BOOST_NO_VARIADIC_TEMPLATES
- member_function_caller<input_ui, person, 0> func;
+ // no variadic templates .. no defaults
+ > func;
 #else
- member_function_caller<input_ui, person, 0> func(
- 0,
- p.street,
- p.number,
- p.city,
- p.postal_code,
- p.country
- );
+ // if variadic templates are supported
+ // we can supply default values for
+ // the parameters before calling the
+ // functor, so we use the current values
+ > func(
+ 0,
+ p.street,
+ p.number,
+ p.city,
+ p.postal_code,
+ p.country
+ );
 #endif
- func(p);
- //
- // TODO: test
- //
- advanced_mem_func_caller<
- input_ui,
- person,
- 0,
- mpl::vector_c<int, 0, 0, 1, 2, 3>
+ // now call the functor on the instance
+ // of person
+ func(p, city, postal_code, country);
+ }
+ else
+ {
+ // if we came here we want the user to
+ // enter all the values
 #ifdef BOOST_NO_VARIADIC_TEMPLATES
- > adv_func;
+ member_function_caller<input_ui, person, 0>
+ func;
 #else
- > adv_func(
- 0,
- p.street,
- p.number,
- p.city,
- p.postal_code,
- p.country
- );
+ member_function_caller<input_ui, person, 0>
+ func(
+ 0,
+ p.street,
+ p.number,
+ p.city,
+ p.postal_code,
+ p.country
+ );
 #endif
- //
- adv_func(p, BOOST_CTS_LIT("Zilina"), BOOST_CTS_LIT("010 07"), BOOST_CTS_LIT("Slovakia"));
- //
- // TODO:
- //
+ func(p);
+ }
                 }
                 // check whether to insert more persons
- do
- {
- cts::bcout() <<
- BOOST_CTS_LIT("Insert more ? (y/n) ") <<
- ::std::flush;
- cts::bcin() >> insert_more;
- cts::bcin().ignore();
- } while(insert_more != yes && insert_more != no);
+ insert_more = yes_no_dlg(BOOST_CTS_LIT("Insert more ? (y/n) "));
         }
         //
         // print out all the persons in the list

Added: sandbox/mirror/libs/mirror/example/factories/yes_no_dlg.hpp
==============================================================================
--- (empty file)
+++ sandbox/mirror/libs/mirror/example/factories/yes_no_dlg.hpp 2009-05-15 05:24:50 EDT (Fri, 15 May 2009)
@@ -0,0 +1,32 @@
+/**
+ * \file examples/factories/yes_no_dlg.cpp
+ *
+ * This example shows how to use the generic function callers.
+ *
+ * Copyright 2008 Matus Chochlik. Distributed under the Boost
+ * Software License, Version 1.0. (See accompanying file
+ * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_MIRROR_EXAMPLES_FACTORIES_YES_NO_DLG_HPP
+#define BOOST_MIRROR_EXAMPLES_FACTORIES_YES_NO_DLG_HPP
+
+#include <boost/char_type_switch/iostream.hpp>
+
+const bool yes_no_dlg(const ::boost::cts::bchar* msg)
+{
+ using namespace ::boost;
+ const cts::bchar yes = BOOST_CTS_LIT('y');
+ const cts::bchar no = BOOST_CTS_LIT('n');
+ cts::bchar result;
+ do
+ {
+ cts::bcout() << msg << ::std::flush;
+ cts::bcin() >> result;
+ cts::bcin().ignore();
+ } while(result != yes && result != no);
+ return result == yes;
+}
+
+#endif
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk