Orocos Real-Time Toolkit  2.5.0
TemplateConstructor.hpp
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  TemplateConstructor.hpp
00003 
00004                         TemplateConstructor.hpp -  description
00005                            -------------------
00006     begin                : Tue September 07 2010
00007     copyright            : (C) 2010 The SourceWorks
00008     email                : peter@thesourceworks.com
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #ifndef ORO_TEMPLATE_CONSTRUCTOR_HPP
00040 #define ORO_TEMPLATE_CONSTRUCTOR_HPP
00041 
00042 #include "Types.hpp"
00043 #include "../internal/FusedFunctorDataSource.hpp"
00044 #include "../internal/CreateSequence.hpp"
00045 #include "../Logger.hpp"
00046 
00047 #include <boost/type_traits/function_traits.hpp>
00048 #include <boost/function.hpp>
00049 
00050 #include "../rtt-config.h"
00051 
00052 namespace RTT
00053 {
00054     namespace types {
00062         template<class S>
00063         struct TemplateConstructor
00064             : public TypeBuilder
00065         {
00066             typedef typename boost::function_traits<S>::result_type result_type;
00067             typedef typename boost::function_traits<S>::arg1_type arg1_type;
00068             typedef internal::create_sequence<typename boost::function_types::parameter_types<S>::type> SequenceFactory;
00069 
00070             boost::function<S> ff;
00071             bool automatic;
00072 
00073             template<class FInit>
00074             TemplateConstructor( FInit f, bool autom)
00075                 : ff(f), automatic(autom)
00076             {}
00077 
00078             virtual base::DataSourceBase::shared_ptr build(const std::vector<base::DataSourceBase::shared_ptr>& args) const {
00079                 // number of arguments must be exact.
00080                 if ( args.size() != boost::function_traits<S>::arity )
00081                     return base::DataSourceBase::shared_ptr();
00082                 try {
00083                     return new internal::FusedFunctorDataSource<S>(ff, SequenceFactory::sources(args.begin()) );
00084                 } catch(...) // wrong argument types
00085                 {}
00086                 return base::DataSourceBase::shared_ptr();
00087             }
00088 
00089             virtual base::DataSourceBase::shared_ptr convert(base::DataSourceBase::shared_ptr arg) const {
00090                 if ( boost::function_traits<S>::arity != 1) {
00091                     return base::DataSourceBase::shared_ptr();
00092                 } else {
00093                     // The compiler should optimise this out...
00094                     // these checks are necessary because produce(args) calls convert, which could lead to endless loops.
00095                     // detect same type converion.
00096                     if ( arg->getTypeInfo() == internal::DataSourceTypeInfo<result_type>::getTypeInfo() ) {
00097                         return arg;
00098                     }
00099                     // detect invalid type conversion.
00100                     if ( arg->getTypeInfo() != internal::DataSourceTypeInfo<arg1_type>::getTypeInfo() ) {
00101                         return base::DataSourceBase::shared_ptr();
00102                     }
00103                     // from now on, it should always succeed.
00104                     std::vector<base::DataSourceBase::shared_ptr> args;
00105                     args.push_back(arg);
00106                     base::DataSourceBase::shared_ptr ret = this->build(args);
00107                     assert( ret );
00108                     if (!automatic)
00109                         log(Warning) << "Conversion from " << arg->getTypeName() << " to " << ret->getTypeName() <<endlog();
00110                     return ret;
00111                 }
00112             }
00113         };
00121     template<class Function>
00122     TypeBuilder* newConstructor( Function* foo, bool automatic = false ) {
00123         return new detail::TemplateConstructor<Function>(foo, automatic);
00124     }
00125 
00134     template<class Object>
00135     TypeBuilder* newConstructor( Object obj, bool automatic = false) {
00136         return new detail::TemplateConstructor<typename Object::Signature>(obj, automatic);
00137     }
00138 }}
00139 
00140 #endif