Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / parameter / aux_ / parenthesized_type.hpp
1 // Copyright David Abrahams 2006. Distributed under the Boost
2 // Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4 #ifndef BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
5 # define BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
6
7 # include <boost/config.hpp>
8 # include <boost/detail/workaround.hpp>
9
10 namespace boost { namespace parameter { namespace aux { 
11
12 // A macro that takes a parenthesized C++ type name (T) and transforms
13 // it into an un-parenthesized type expression equivalent to T.
14 #  define BOOST_PARAMETER_PARENTHESIZED_TYPE(x)                    \
15     boost::parameter::aux::unaryfunptr_arg_type< void(*)x >::type
16
17 // A metafunction that transforms void(*)(T) -> T
18 template <class UnaryFunctionPointer>
19 struct unaryfunptr_arg_type;
20
21 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
22
23 template <class Arg>
24 struct unaryfunptr_arg_type<void(*)(Arg)>
25 {
26     typedef Arg type;
27 };
28
29 # else
30
31 // Use the "native typeof" bugfeatures of older versions of MSVC to
32 // accomplish what we'd normally do with partial specialization.  This
33 // capability was discovered by Igor Chesnokov.
34
35 #  if BOOST_WORKAROUND(BOOST_MSVC, != 1300)
36
37 // This version applies to VC6.5 and VC7.1 (except that we can just
38 // use partial specialization for the latter in this case).
39
40 // This gets used as a base class.  
41 template<typename Address>
42 struct msvc_type_memory
43 {
44     // A nullary metafunction that will yield the Value type "stored"
45     // at this Address.
46     struct storage;
47 };
48
49 template<typename Value, typename Address>
50 struct msvc_store_type : msvc_type_memory<Address>
51 {
52     // VC++ somehow lets us define the base's nested storage
53     // metafunction here, where we have the Value type we'd like to
54     // "store" in it.  Later we can come back to the base class and
55     // extract the "stored type."
56     typedef msvc_type_memory<Address> location;
57     struct location::storage 
58     {
59         typedef Value type;
60     };
61 };
62
63 #  else
64
65 // This slightly more complicated version of the same thing is
66 // required for msvc-7.0
67 template<typename Address>
68 struct msvc_type_memory
69 {
70     template<bool>
71     struct storage_impl;
72
73     typedef storage_impl<true> storage;
74 };
75
76 template<typename Value, typename Address>
77 struct msvc_store_type : msvc_type_memory<Address>
78 {
79     // Rather than supplying a definition for the base class' nested
80     // class, we specialize the base class' nested template
81     template<>
82     struct storage_impl<true>  
83     {
84         typedef Value type;
85     };
86 };
87
88 #  endif
89
90 // Function template argument deduction does many of the same things
91 // as type matching during partial specialization, so we call a
92 // function template to "store" T into the type memory addressed by
93 // void(*)(T).
94 template <class T>
95 msvc_store_type<T,void(*)(T)>
96 msvc_store_argument_type(void(*)(T));
97
98 template <class FunctionPointer>
99 struct unaryfunptr_arg_type
100 {
101     // We don't want the function to be evaluated, just instantiated,
102     // so protect it inside of sizeof.
103     enum { dummy = sizeof(msvc_store_argument_type((FunctionPointer)0)) };
104
105     // Now pull the type out of the instantiated base class
106     typedef typename msvc_type_memory<FunctionPointer>::storage::type type;
107 };
108
109 # endif
110
111 template <>
112 struct unaryfunptr_arg_type<void(*)(void)>
113 {
114     typedef void type;
115 };
116     
117 }}} // namespace boost::parameter::aux
118
119 #endif // BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP