diff --git a/include/boost/type_traits/common_type.hpp b/include/boost/type_traits/common_type.hpp index 33ac158..5c4303b 100644 --- a/include/boost/type_traits/common_type.hpp +++ b/include/boost/type_traits/common_type.hpp @@ -17,6 +17,10 @@ #include #endif +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include +#endif + namespace boost { @@ -28,11 +32,31 @@ template struct common_type { }; +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template using common_type_t = typename common_type::type; + +namespace type_traits_detail +{ + +template using common_type_fold = common_type_t, T...>; + +} // namespace type_traits_detail + +template +struct common_type: type_traits_detail::mp_defer +{ +}; + +#else + template struct common_type: common_type::type, T...> { }; +#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + #else template< @@ -61,10 +85,42 @@ namespace type_traits_detail #if !defined(BOOST_NO_CXX11_DECLTYPE) +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1800 + +// internal compiler error on msvc-12.0 + +template using builtin_common_type = typename boost::decay()? boost::declval(): boost::declval() )>::type; + +template struct common_type_impl: mp_defer +{ +}; + +#else + +template using builtin_common_type = decltype( boost::declval()? boost::declval(): boost::declval() ); + +template struct common_type_impl_2: mp_defer +{ +}; + +template using decay_common_type = typename boost::decay::type>::type; + +template struct common_type_impl: mp_defer +{ +}; + +#endif // !defined(BOOST_MSVC) || BOOST_MSVC > 1800 + +#else + template struct common_type_impl: boost::decay()? boost::declval(): boost::declval() )> { }; +#endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + #endif // #if !defined(BOOST_NO_CXX11_DECLTYPE) // decay helper diff --git a/include/boost/type_traits/detail/mp_defer.hpp b/include/boost/type_traits/detail/mp_defer.hpp new file mode 100644 index 0000000..7910e54 --- /dev/null +++ b/include/boost/type_traits/detail/mp_defer.hpp @@ -0,0 +1,56 @@ +#ifndef BOOST_TYPE_TRAITS_DETAIL_MP_DEFER_HPP_INCLUDED +#define BOOST_TYPE_TRAITS_DETAIL_MP_DEFER_HPP_INCLUDED + +// +// Copyright 2015 Peter Dimov +// +// 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 +// + +#include +#include + +namespace boost +{ + +namespace type_traits_detail +{ + +// mp_valid +// implementation by Bruno Dutra (by the name is_evaluable) + +template class F, class... T> +struct mp_valid_impl +{ + template class G, class = G> + static boost::true_type check(int); + + template class> + static boost::false_type check(...); + + using type = decltype(check(0)); +}; + +template class F, class... T> +using mp_valid = typename mp_valid_impl::type; + +// mp_defer + +struct mp_empty +{ +}; + +template class F, class... T> struct mp_defer_impl +{ + using type = F; +}; + +template class F, class... T> using mp_defer = typename boost::conditional::value, mp_defer_impl, mp_empty>::type; + +} // namespace type_traits_detail + +} // namespace boost + +#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_MP_DEFER_HPP_INCLUDED diff --git a/test/common_type_6_test.cpp b/test/common_type_6_test.cpp new file mode 100644 index 0000000..e5ad774 --- /dev/null +++ b/test/common_type_6_test.cpp @@ -0,0 +1,39 @@ + +// Copyright Peter Dimov 2015 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.tt.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "check_type.hpp" +#ifdef TEST_STD +# include +#else +# include +#endif +#include + +struct X {}; +struct Y: X {}; + +TT_TEST_BEGIN(common_type_6) +{ + // binary case + + BOOST_CHECK_TYPE3(tt::common_type::type, void); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + + BOOST_CHECK_TYPE3(tt::common_type::type, X); + BOOST_CHECK_TYPE3(tt::common_type::type, X); + BOOST_CHECK_TYPE3(tt::common_type::type, X); + + BOOST_CHECK_TYPE3(tt::common_type::type, X); + BOOST_CHECK_TYPE3(tt::common_type::type, X); + BOOST_CHECK_TYPE3(tt::common_type::type, X); + BOOST_CHECK_TYPE3(tt::common_type::type, X); + BOOST_CHECK_TYPE3(tt::common_type::type, X); +} +TT_TEST_END diff --git a/test/common_type_sfinae2_test.cpp b/test/common_type_sfinae2_test.cpp new file mode 100644 index 0000000..2e585cf --- /dev/null +++ b/test/common_type_sfinae2_test.cpp @@ -0,0 +1,39 @@ + +// Copyright Peter Dimov 2015 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.tt.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "check_integral_constant.hpp" +#ifdef TEST_STD +# include +#else +# include +# include +#endif +#include + +typedef char(&s1)[1]; +typedef char(&s2)[2]; + +template s1 has_type_impl( typename T::type * ); +template s2 has_type_impl( ... ); + +template struct has_type: tt::integral_constant(0)) == sizeof(s1)> {}; + +struct X {}; +struct Y {}; + +TT_TEST_BEGIN(common_type_sfinae2) +{ +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type >::value), false ); + BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type >::value), false ); + BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type >::value), false ); + BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type >::value), false ); + +#endif +} +TT_TEST_END diff --git a/test/common_type_sfinae_test.cpp b/test/common_type_sfinae_test.cpp new file mode 100644 index 0000000..55aa3fe --- /dev/null +++ b/test/common_type_sfinae_test.cpp @@ -0,0 +1,45 @@ + +// Copyright Peter Dimov 2015 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.tt.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include "check_type.hpp" +#ifdef TEST_STD +# include +#else +# include +#endif +#include + +struct X {}; +struct Y {}; + +TT_TEST_BEGIN(common_type_sfinae) +{ +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + { + tt::common_type tmp; + (void)tmp; + } + + { + tt::common_type tmp; + (void)tmp; + } + + { + tt::common_type tmp; + (void)tmp; + } + + { + tt::common_type tmp; + (void)tmp; + } + +#endif +} +TT_TEST_END