全部前にもってくる

型修飾子を識別子の前に持ってこれるようにした。

#if !defined EXIST_DECLARE_HPP_INCLUDED
#define EXIST_DECLARE_HPP_INCLUDED

#include <boost/function_types/function_type.hpp>
#include <boost/function_types/member_function_pointer.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/property_tags.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_volatile.hpp>
#include <boost/type_traits/add_cv.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility.hpp>


namespace exist { namespace declare { namespace detail {

namespace mpl = boost::mpl;

using boost::is_function;
using boost::function_traits;
using boost::function_types::function_type;
using boost::function_types::member_function_pointer;
using boost::function_types::parameter_types;
using boost::function_types::null_tag;
using mpl::_;
using mpl::back_inserter;
using mpl::begin;
using mpl::copy;
using mpl::deref;
using mpl::eval_if;
using mpl::find_if;
using mpl::identity;
using mpl::iterator_range;
using mpl::push_front;
using mpl::vector;
using mpl::void_;

template<typename Seq, typename F>
struct take_while {
typedef iterator_range<
typename begin<Seq>::type,
typename find_if<Seq, F>::type> type;
};

template<typename T, typename C, typename Tag>
struct mem_fun_type {
typedef typename
member_function_pointer<
typename push_front<
typename push_front<
typename copy<
typename parameter_types<T, null_tag>::type,
back_inserter<vector<> > >::type,
C>::type,
typename function_traits<T>::result_type>::type,
Tag>::type
type;
};


template<typename T, typename True, typename False = identity<T> >
struct eval_if_function : public eval_if<is_function<T>, True, False> {};

template<typename T, typename True, typename False = identity<T> >
struct eval_if_not_function : public eval_if_function<T, False, True> {};

template<typename T>
struct add_pointer_if_function : public eval_if_function<T, boost::add_pointer<T> > {};


} // namespace detail


template<typename T>
struct declare {
typedef typename detail::add_pointer_if_function<T>::type type;
typedef declare<typename boost::add_pointer<T>::type> ptr;
typedef declare<typename boost::add_reference<T>::type> ref;
typedef declare<typename detail::eval_if_not_function<T, boost::add_const<T> >::type> const_;
typedef declare<typename detail::eval_if_not_function<T, boost::add_volatile<T> >::type> volatile_;
typedef declare<typename detail::eval_if_not_function<T, boost::add_cv<T> >::type> cv_;
template<size_t N>
struct array : public declare<T[N]> {};
template<typename A0 = boost::mpl::void_,
typename A1 = boost::mpl::void_,
typename A2 = boost::mpl::void_,
typename A3 = boost::mpl::void_,
typename A4 = boost::mpl::void_,
typename A5 = boost::mpl::void_,
typename A6 = boost::mpl::void_,
typename A7 = boost::mpl::void_,
typename A8 = boost::mpl::void_,
typename A9 = boost::mpl::void_>
struct args : public
declare<
typename boost::function_types::function_type<
typename detail::take_while<
boost::mpl::vector<typename detail::add_pointer_if_function<T>::type, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>,
boost::is_same<boost::mpl::_, boost::mpl::void_> >::type>::type>
{};

template<typename C>
struct mem_obj_of : public declare<typename detail::add_pointer_if_function<T>::type C::*> {};
template<typename C>
struct mem_fun_of : public
declare<typename detail::eval_if_function<
T,
detail::mem_fun_type<T, C, boost::function_types::null_tag>,
boost::mpl::void_>::type>
{};
template<typename C>
struct const_mem_fun_of : public
declare<typename detail::eval_if_function<
T,
detail::mem_fun_type<T, C, boost::function_types::const_qualified>,
boost::mpl::void_>::type>
{};
template<typename C>
struct volatile_mem_fun_of : public
declare<typename detail::eval_if_function<
T,
detail::mem_fun_type<T, C, boost::function_types::volatile_qualified>,
boost::mpl::void_>::type>
{};
template<typename C>
struct cv_mem_fun_of : public
declare<typename detail::eval_if_function<
T,
detail::mem_fun_type<T, C, boost::function_types::cv_qualified>,
boost::mpl::void_>::type>
{};
};

}} // namespace exist { namespace declare {

#endif // DECLARE_HPP_INCLUDED

使い方:

#include "exist/declare.hpp"

int f(int, int) {
return 0;
}

struct Foo {
int g() { return 0; }
int h(double &, char) const { return 0; }
};

using exist::declare::declare;

declare<int>::args<int, int>::type pf = f; // int (* pf)(int, int)
declare<int>::args<>::mem_fun_of<Foo>::array<3>::type amf = { &Foo::g, &Foo::g, &Foo::g, }; // int (Foo::* amf[3])();
declare<int>::args<double &, char>::const_mem_fun_of<Foo>::const_::type pmf = &Foo::h; // int (Foo::* const pmf)(double &, char) const;

関数型だった場合は適当にポインタ修飾を補ったりする。作ったはいいけどそこまでややこしい修飾を施して宣言する型を使うことがあるのだろうか?