libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/declare.hpp
Go to the documentation of this file.
00001 
00013 /*
00014  *  Copyright (C) 2010 Juan Pedro Bolivar Puente
00015  *
00016  *  This file is part of Psychosynth.
00017  *   
00018  *  Psychosynth is free software: you can redistribute it and/or modify
00019  *  it under the terms of the GNU General Public License as published by
00020  *  the Free Software Foundation, either version 3 of the License, or
00021  *  (at your option) any later version.
00022  *
00023  *  Psychosynth is distributed in the hope that it will be useful,
00024  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00025  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026  *  GNU General Public License for more details.
00027  *
00028  *  You should have received a copy of the GNU General Public License
00029  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00030  *
00031  */
00032 
00033 #ifndef PSYNTH_BASE_DECLARE_H_
00034 #define PSYNTH_BASE_DECLARE_H_
00035 
00036 #include <utility>
00037 #include <memory>
00038 
00039 #include <boost/preprocessor/cat.hpp>
00040 #include <boost/preprocessor/seq/size.hpp>
00041 #include <boost/preprocessor/seq/for_each_i.hpp>
00042 #include <boost/preprocessor/repetition/enum_params.hpp>
00043 
00044 #include <psynth/base/preprocessor.hpp>
00045 
00046 namespace psynth
00047 {
00048 namespace base
00049 {
00050 
00051 #define PSYNTH_DECLARE_SHARED_POINTER(type_name)                        \
00052     typedef std::shared_ptr<type_name> type_name ## _ptr;               \
00053     typedef std::weak_ptr<type_name> type_name ## _weak_ptr;            \
00054     template <typename... Args>                                         \
00055     type_name ## _ptr new_ ## type_name (Args && ... args)              \
00056     {                                                                   \
00057         return std::make_shared <type_name> (                           \
00058             std::forward<Args>(args) ...);                              \
00059     }
00060 
00061 #define PSYNTH_DECLARE_TYPE(type_name)          \
00062     struct type_name;
00063 
00064 #define PSYNTH_DECLARE_SHARED_TYPE(type_name)   \
00065     PSYNTH_DECLARE_TYPE (type_name)             \
00066     PSYNTH_DECLARE_SHARED_POINTER (type_name)
00067 
00068 
00072 #define PSYNTH_DECLARE_SHARED_POINTER_TEMPLATE(type_name, ...)          \
00073     PSYNTH_DECLARE_SHARED_POINTER_TEMPLATE_IMPL(                        \
00074         type_name, PSYNTH_VARG_TO_SEQ(__VA_ARGS__))
00075 
00076 #define PSYNTH_TEMPLATE_PARAM_ITER(r, data, i, elem)    \
00077     BOOST_PP_COMMA_IF(i) elem BOOST_PP_CAT(Par__, i)
00078 
00079 #define PSYNTH_TEMPLATE_PARAMS_FULL(param_seq)                          \
00080     BOOST_PP_SEQ_FOR_EACH_I(PSYNTH_TEMPLATE_PARAM_ITER, _, param_seq)
00081 
00082 #define PSYNTH_TEMPLATE_PARAMS(param_seq) \
00083     BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(param_seq), Par__)
00084 
00085 // TODO: Make this generate a weak pointer alias too?
00086 #define PSYNTH_DECLARE_SHARED_POINTER_TEMPLATE_IMPL(type_name, param_seq) \
00087     template <PSYNTH_TEMPLATE_PARAMS_FULL(param_seq)>                   \
00088     struct type_name ## _ptr :                                          \
00089         public std::shared_ptr<type_name <PSYNTH_TEMPLATE_PARAMS(param_seq)> > \
00090     {                                                                   \
00091         typedef std::shared_ptr<type_name <PSYNTH_TEMPLATE_PARAMS(param_seq)> > base; \
00092         template <typename... Args>                                     \
00093             type_name ## _ptr (Args&&... args)                          \
00094             : base (std::forward<Args> (args) ...) {}                   \
00095         template <typename... Args>                                     \
00096             type_name ## _ptr& operator= (Args&&... args)               \
00097             { this->base::operator= (std::forward<Args> (args) ...); return *this; } \
00098     };                                                                  \
00099                                                                         \
00100     template <PSYNTH_TEMPLATE_PARAMS_FULL(param_seq), typename... Args> \
00101     type_name ## _ptr<PSYNTH_TEMPLATE_PARAMS(param_seq)>                \
00102     inline new_ ## type_name (Args && ... args)                                \
00103     {                                                                   \
00104         return                                                          \
00105             std::make_shared <type_name <PSYNTH_TEMPLATE_PARAMS(param_seq)> > \
00106             (std::forward<Args>(args)...);                              \
00107     }
00108 
00109 #define PSYNTH_DECLARE_TEMPLATE(type_name, ...)                     \
00110     template <__VA_ARGS__>                                          \
00111     struct type_name;
00112 
00113 #define PSYNTH_DECLARE_SHARED_TEMPLATE(type_name, ...)                  \
00114     PSYNTH_DECLARE_TEMPLATE (type_name, __VA_ARGS__)                    \
00115     PSYNTH_DECLARE_SHARED_POINTER_TEMPLATE (type_name, __VA_ARGS__)
00116 
00117 } /* namespace base */
00118 } /* namespace psynth */
00119 
00120 
00121 #endif /* PSYNTH_BASE_DECLARE_H_ */