forked from boostorg/type_traits
Make common_type SFINAE-friendly, add tests
This commit is contained in:
@ -17,6 +17,10 @@
|
||||
#include <boost/type_traits/detail/common_type_impl.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#include <boost/type_traits/detail/mp_defer.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
@ -28,11 +32,31 @@ template<class... T> struct common_type
|
||||
{
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
|
||||
|
||||
template<class... T> using common_type_t = typename common_type<T...>::type;
|
||||
|
||||
namespace type_traits_detail
|
||||
{
|
||||
|
||||
template<class T1, class T2, class... T> using common_type_fold = common_type_t<common_type_t<T1, T2>, T...>;
|
||||
|
||||
} // namespace type_traits_detail
|
||||
|
||||
template<class T1, class T2, class... T>
|
||||
struct common_type<T1, T2, T...>: type_traits_detail::mp_defer<type_traits_detail::common_type_fold, T1, T2, T...>
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class T1, class T2, class... T>
|
||||
struct common_type<T1, T2, T...>: common_type<typename common_type<T1, T2>::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<class T1, class T2> using builtin_common_type = typename boost::decay<decltype( boost::declval<bool>()? boost::declval<T1>(): boost::declval<T2>() )>::type;
|
||||
|
||||
template<class T1, class T2> struct common_type_impl: mp_defer<builtin_common_type, T1, T2>
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class T1, class T2> using builtin_common_type = decltype( boost::declval<bool>()? boost::declval<T1>(): boost::declval<T2>() );
|
||||
|
||||
template<class T1, class T2> struct common_type_impl_2: mp_defer<builtin_common_type, T1, T2>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T1, class T2> using decay_common_type = typename boost::decay<typename common_type_impl_2<T1, T2>::type>::type;
|
||||
|
||||
template<class T1, class T2> struct common_type_impl: mp_defer<decay_common_type, T1, T2>
|
||||
{
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_MSVC) || BOOST_MSVC > 1800
|
||||
|
||||
#else
|
||||
|
||||
template<class T1, class T2> struct common_type_impl: boost::decay<decltype( boost::declval<bool>()? boost::declval<T1>(): boost::declval<T2>() )>
|
||||
{
|
||||
};
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_DECLTYPE)
|
||||
|
||||
// decay helper
|
||||
|
56
include/boost/type_traits/detail/mp_defer.hpp
Normal file
56
include/boost/type_traits/detail/mp_defer.hpp
Normal file
@ -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 <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/conditional.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace type_traits_detail
|
||||
{
|
||||
|
||||
// mp_valid
|
||||
// implementation by Bruno Dutra (by the name is_evaluable)
|
||||
|
||||
template<template<class...> class F, class... T>
|
||||
struct mp_valid_impl
|
||||
{
|
||||
template<template<class...> class G, class = G<T...>>
|
||||
static boost::true_type check(int);
|
||||
|
||||
template<template<class...> class>
|
||||
static boost::false_type check(...);
|
||||
|
||||
using type = decltype(check<F>(0));
|
||||
};
|
||||
|
||||
template<template<class...> class F, class... T>
|
||||
using mp_valid = typename mp_valid_impl<F, T...>::type;
|
||||
|
||||
// mp_defer
|
||||
|
||||
struct mp_empty
|
||||
{
|
||||
};
|
||||
|
||||
template<template<class...> class F, class... T> struct mp_defer_impl
|
||||
{
|
||||
using type = F<T...>;
|
||||
};
|
||||
|
||||
template<template<class...> class F, class... T> using mp_defer = typename boost::conditional<mp_valid<F, T...>::value, mp_defer_impl<F, T...>, mp_empty>::type;
|
||||
|
||||
} // namespace type_traits_detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_MP_DEFER_HPP_INCLUDED
|
39
test/common_type_6_test.cpp
Normal file
39
test/common_type_6_test.cpp
Normal file
@ -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 <type_traits>
|
||||
#else
|
||||
# include <boost/type_traits/common_type.hpp>
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
struct X {};
|
||||
struct Y: X {};
|
||||
|
||||
TT_TEST_BEGIN(common_type_6)
|
||||
{
|
||||
// binary case
|
||||
|
||||
BOOST_CHECK_TYPE3(tt::common_type<void, void>::type, void);
|
||||
|
||||
BOOST_CHECK_TYPE3(tt::common_type<int, int>::type, int);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<int&, int&>::type, int);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<int&, int const&>::type, int);
|
||||
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X, X>::type, X);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X&, X&>::type, X);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X&, X const&>::type, X);
|
||||
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X, Y>::type, X);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X&, Y&>::type, X);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X const&, Y&>::type, X);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X&, Y const&>::type, X);
|
||||
BOOST_CHECK_TYPE3(tt::common_type<X const&, Y const&>::type, X);
|
||||
}
|
||||
TT_TEST_END
|
39
test/common_type_sfinae2_test.cpp
Normal file
39
test/common_type_sfinae2_test.cpp
Normal file
@ -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 <type_traits>
|
||||
#else
|
||||
# include <boost/type_traits/common_type.hpp>
|
||||
# include <boost/type_traits/integral_constant.hpp>
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
typedef char(&s1)[1];
|
||||
typedef char(&s2)[2];
|
||||
|
||||
template<class T> s1 has_type_impl( typename T::type * );
|
||||
template<class T> s2 has_type_impl( ... );
|
||||
|
||||
template<class T> struct has_type: tt::integral_constant<bool, sizeof(has_type_impl<T>(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<int, void*> >::value), false );
|
||||
BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type<X, Y> >::value), false );
|
||||
BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type<X&, int const*> >::value), false );
|
||||
BOOST_CHECK_INTEGRAL_CONSTANT( (has_type< tt::common_type<X, Y, int, void*> >::value), false );
|
||||
|
||||
#endif
|
||||
}
|
||||
TT_TEST_END
|
45
test/common_type_sfinae_test.cpp
Normal file
45
test/common_type_sfinae_test.cpp
Normal file
@ -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 <type_traits>
|
||||
#else
|
||||
# include <boost/type_traits/common_type.hpp>
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
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<int, void*> tmp;
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
{
|
||||
tt::common_type<X, Y> tmp;
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
{
|
||||
tt::common_type<X&, int const*> tmp;
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
{
|
||||
tt::common_type<X, Y, int, void*> tmp;
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
TT_TEST_END
|
Reference in New Issue
Block a user