tinympl  0.2
mini MPL library for C++11
bind.hpp
1 // Copyright (C) 2013, Ennio Barbaro.
2 //
3 // Use, modification, and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://sbabbi.github.io/tinympl for documentation.
8 //
9 // You are welcome to contact the author at:
10 // enniobarbaro@gmail.com
11 //
12 
13 #ifndef TINYMPL_BIND_HPP
14 #define TINYMPL_BIND_HPP
15 
16 #include <tinympl/variadic.hpp>
17 
18 namespace tinympl {
19 
43 template< template<class ... T> class F,class ... Args> struct bind;
44 
45 template<std::size_t> struct arg;
46 typedef arg<1> arg1;
47 typedef arg<2> arg2;
48 typedef arg<3> arg3;
49 typedef arg<4> arg4;
50 typedef arg<5> arg5;
51 typedef arg<6> arg6;
52 typedef arg<7> arg7;
53 typedef arg<8> arg8;
54 
59 template<class T> struct is_placeholder : std::integral_constant<std::size_t, 0> {};
60 template<std::size_t i> struct is_placeholder< arg<i> > : std::integral_constant<std::size_t, i>
61 {
62  static_assert(i != 0, "Placeholder arg<0> is undefined");
63 };
64 
68 template<class T> struct is_bind_expression : std::false_type {};
69 template<template<class ... T> class F,class ... Args> struct is_bind_expression< bind<F,Args...> > : std::true_type {};
70 
73 template< template<class ... T> class F,class Head,class ... Tail> struct bind<F,Head,Tail...>
74 {
75 private:
76  template<class ... Args>
77  struct call
78  {
79  template<class ... BoundArgs>
80  struct eval
81  {
82  template<class T,class Enable = void> struct pick {typedef T type;};
83  template<class T> struct pick<T, typename std::enable_if< (is_placeholder<T>::value > 0) >::type> {typedef variadic::at_t<is_placeholder<T>::value-1, Args ... > type;};
84  template<class T> struct pick<T, typename std::enable_if< is_bind_expression<T>::type::value>::type> {typedef typename T::template eval<Args...>::type type;};
85 
86  typedef typename pick<Head>::type argument_t;
87 
88  //Forward the call to bind
89  typedef typename bind<F,Tail...>::template call<Args...>::template eval<BoundArgs..., argument_t>::type type;
90  };
91  };
92 
93  template< template<class ...> class,class ...> friend struct bind;
94 
95 public:
96  template<class ... Args>
97  struct eval
98  {
99  using type = typename call<Args...>::template eval<>::type;
100  };
101 
102  template<class ... Args>
103  using eval_t = typename eval<Args...>::type;
104 };
105 
106 template< template<class ... T> class F> struct bind<F>
107 {
108 private:
109  template<class ... Args>
110  struct call
111  {
112  template<class ... BoundArgs>
113  struct eval
114  {
115  typedef typename F<BoundArgs...>::type type;
116  };
117  };
118 
119  template< template<class ...> class,class ...> friend struct bind;
120 
121 public:
122  template<class ... Args>
123  struct eval
124  {
125  using type = typename call<Args...>::template eval<>::type;
126  };
127 
128  template<class ... Args>
129  using eval_t = typename eval<Args...>::type;
130 };
131 
132 }
133 
134 #endif // MPL_BIND_HPP
Determine whether a type is a placeholder. is_placeholder::value is 0 if T is not a placeholder...
Definition: bind.hpp:59
Produce a template type by binding the given arguments on the passed template template.
Definition: bind.hpp:43
Determine whether a type is a bind expression.
Definition: bind.hpp:68