$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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
+