120 lines
3.4 KiB
C++
120 lines
3.4 KiB
C++
// Copyright David Abrahams 2006. Distributed under the Boost
|
|
// Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
#ifndef BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
|
|
# define BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
|
|
|
|
# include <boost/config.hpp>
|
|
# include <boost/detail/workaround.hpp>
|
|
|
|
namespace boost { namespace parameter { namespace aux {
|
|
|
|
// A macro that takes a parenthesized C++ type name (T) and transforms
|
|
// it into an un-parenthesized type expression equivalent to T.
|
|
# define BOOST_PARAMETER_PARENTHESIZED_TYPE(x) \
|
|
boost::parameter::aux::unaryfunptr_arg_type< void(*)x >::type
|
|
|
|
// A metafunction that transforms void(*)(T) -> T
|
|
template <class UnaryFunctionPointer>
|
|
struct unaryfunptr_arg_type;
|
|
|
|
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
|
|
|
template <class Arg>
|
|
struct unaryfunptr_arg_type<void(*)(Arg)>
|
|
{
|
|
typedef Arg type;
|
|
};
|
|
|
|
# else
|
|
|
|
// Use the "native typeof" bugfeatures of older versions of MSVC to
|
|
// accomplish what we'd normally do with partial specialization. This
|
|
// capability was discovered by Igor Chesnokov.
|
|
|
|
# if BOOST_WORKAROUND(BOOST_MSVC, != 1300)
|
|
|
|
// This version applies to VC6.5 and VC7.1 (except that we can just
|
|
// use partial specialization for the latter in this case).
|
|
|
|
// This gets used as a base class.
|
|
template<typename Address>
|
|
struct msvc_type_memory
|
|
{
|
|
// A nullary metafunction that will yield the Value type "stored"
|
|
// at this Address.
|
|
struct storage;
|
|
};
|
|
|
|
template<typename Value, typename Address>
|
|
struct msvc_store_type : msvc_type_memory<Address>
|
|
{
|
|
// VC++ somehow lets us define the base's nested storage
|
|
// metafunction here, where we have the Value type we'd like to
|
|
// "store" in it. Later we can come back to the base class and
|
|
// extract the "stored type."
|
|
typedef msvc_type_memory<Address> location;
|
|
struct location::storage
|
|
{
|
|
typedef Value type;
|
|
};
|
|
};
|
|
|
|
# else
|
|
|
|
// This slightly more complicated version of the same thing is
|
|
// required for msvc-7.0
|
|
template<typename Address>
|
|
struct msvc_type_memory
|
|
{
|
|
template<bool>
|
|
struct storage_impl;
|
|
|
|
typedef storage_impl<true> storage;
|
|
};
|
|
|
|
template<typename Value, typename Address>
|
|
struct msvc_store_type : msvc_type_memory<Address>
|
|
{
|
|
// Rather than supplying a definition for the base class' nested
|
|
// class, we specialize the base class' nested template
|
|
template<>
|
|
struct storage_impl<true>
|
|
{
|
|
typedef Value type;
|
|
};
|
|
};
|
|
|
|
# endif
|
|
|
|
// Function template argument deduction does many of the same things
|
|
// as type matching during partial specialization, so we call a
|
|
// function template to "store" T into the type memory addressed by
|
|
// void(*)(T).
|
|
template <class T>
|
|
msvc_store_type<T,void(*)(T)>
|
|
msvc_store_argument_type(void(*)(T));
|
|
|
|
template <class FunctionPointer>
|
|
struct unaryfunptr_arg_type
|
|
{
|
|
// We don't want the function to be evaluated, just instantiated,
|
|
// so protect it inside of sizeof.
|
|
enum { dummy = sizeof(msvc_store_argument_type((FunctionPointer)0)) };
|
|
|
|
// Now pull the type out of the instantiated base class
|
|
typedef typename msvc_type_memory<FunctionPointer>::storage::type type;
|
|
};
|
|
|
|
# endif
|
|
|
|
template <>
|
|
struct unaryfunptr_arg_type<void(*)(void)>
|
|
{
|
|
typedef void type;
|
|
};
|
|
|
|
}}} // namespace boost::parameter::aux
|
|
|
|
#endif // BOOST_PARAMETER_AUX_PARENTHESIZED_TYPE_DWA2006414_HPP
|