diff --git a/include/boost/type_traits/is_constructible.hpp b/include/boost/type_traits/is_constructible.hpp index d1accc1..9b7abe8 100644 --- a/include/boost/type_traits/is_constructible.hpp +++ b/include/boost/type_traits/is_constructible.hpp @@ -15,6 +15,7 @@ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) #include +#include #include #include @@ -47,6 +48,13 @@ namespace boost{ template struct is_constructible : public integral_constant(detail::tt_declval())) == sizeof(boost::type_traits::yes_type)>{}; template struct is_constructible : public integral_constant(detail::tt_declval())) == sizeof(boost::type_traits::yes_type)>{}; + template <> struct is_constructible : public false_type{}; + template <> struct is_constructible : public false_type{}; + template <> struct is_constructible : public false_type{}; + template <> struct is_constructible : public false_type{}; + + template struct is_constructible : public is_default_constructible{}; + #else #include @@ -57,6 +65,14 @@ namespace boost{ // We don't know how to implement this: template struct is_constructible : public is_convertible{}; template struct is_constructible : public is_default_constructible{}; + template <> struct is_constructible : public false_type{}; + template <> struct is_constructible : public false_type{}; + template <> struct is_constructible : public false_type{}; + template <> struct is_constructible : public false_type{}; + template struct is_constructible : public false_type{}; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template struct is_constructible : public false_type{}; +#endif #endif } // namespace boost diff --git a/include/boost/type_traits/is_copy_constructible.hpp b/include/boost/type_traits/is_copy_constructible.hpp index 2e80738..03c0460 100644 --- a/include/boost/type_traits/is_copy_constructible.hpp +++ b/include/boost/type_traits/is_copy_constructible.hpp @@ -9,111 +9,170 @@ #ifndef BOOST_TT_IS_COPY_CONSTRUCTIBLE_HPP_INCLUDED #define BOOST_TT_IS_COPY_CONSTRUCTIBLE_HPP_INCLUDED +#include +#include + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) + +#include + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1800) + +namespace boost { + +template struct is_copy_constructible : public boost::is_constructible{}; + +template <> struct is_copy_constructible : public false_type{}; +template <> struct is_copy_constructible : public false_type{}; +template <> struct is_copy_constructible : public false_type{}; +template <> struct is_copy_constructible : public false_type{}; + +} // namespace boost + +#else +// +// Special version for VC12 which has a problem when a base class (such as non_copyable) has a deleted +// copy constructor. In this case the compiler thinks there really is a copy-constructor and tries to +// instantiate the deleted member. std::is_copy_constructible has the same issue (or at least returns +// an incorrect value, which just defers the issue into the users code) as well. We can at least fix +// boost::non_copyable as a base class as a special case: +// +#include +#include + +namespace boost { + + namespace detail + { + + template struct is_copy_constructible_imp : public boost::is_constructible{}; + template struct is_copy_constructible_imp : public false_type{}; + + } + + template struct is_copy_constructible : public detail::is_copy_constructible_imp::value>{}; + + template <> struct is_copy_constructible : public false_type{}; + template <> struct is_copy_constructible : public false_type{}; + template <> struct is_copy_constructible : public false_type{}; + template <> struct is_copy_constructible : public false_type{}; + +} // namespace boost + +#endif + +#else + #include #include #include #include #include +#include +#include #include namespace boost { -namespace detail{ + namespace detail{ -template -struct is_copy_constructible_impl2 { + template + struct is_copy_constructible_impl2 { -// Intel compiler has problems with SFINAE for copy constructors and deleted functions: -// -// error: function *function_name* cannot be referenced -- it is a deleted function -// static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval()))* = 0); -// ^ -// -// MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See: -// https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken + // Intel compiler has problems with SFINAE for copy constructors and deleted functions: + // + // error: function *function_name* cannot be referenced -- it is a deleted function + // static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval()))* = 0); + // ^ + // + // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See: + // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_INTEL_CXX_VERSION) && !(defined(BOOST_MSVC) && _MSC_VER == 1800) #ifdef BOOST_NO_CXX11_DECLTYPE - template - static boost::type_traits::yes_type test(T1&, boost::mpl::int_()))>* = 0); + template + static boost::type_traits::yes_type test(const T1&, boost::mpl::int_()))>* = 0); #else - template - static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval()))* = 0); + template + static boost::type_traits::yes_type test(const T1&, decltype(T1(boost::declval()))* = 0); #endif - static boost::type_traits::no_type test(...); + static boost::type_traits::no_type test(...); #else - template - static boost::type_traits::no_type test(T1&, typename T1::boost_move_no_copy_constructor_or_assign* = 0); - static boost::type_traits::yes_type test(...); + template + static boost::type_traits::no_type test(const T1&, typename T1::boost_move_no_copy_constructor_or_assign* = 0); + static boost::type_traits::yes_type test(...); #endif - // If you see errors like this: - // - // `'T::T(const T&)' is private` - // `boost/type_traits/is_copy_constructible.hpp:68:5: error: within this context` - // - // then you are trying to call that macro for a structure defined like that: - // - // struct T { - // ... - // private: - // T(const T &); - // ... - // }; - // - // To fix that you must modify your structure: - // - // // C++03 and C++11 version - // struct T: private boost::noncopyable { - // ... - // private: - // T(const T &); - // ... - // }; - // - // // C++11 version - // struct T { - // ... - // private: - // T(const T &) = delete; - // ... - // }; - BOOST_STATIC_CONSTANT(bool, value = ( + // If you see errors like this: + // + // `'T::T(const T&)' is private` + // `boost/type_traits/is_copy_constructible.hpp:68:5: error: within this context` + // + // then you are trying to call that macro for a structure defined like that: + // + // struct T { + // ... + // private: + // T(const T &); + // ... + // }; + // + // To fix that you must modify your structure: + // + // // C++03 and C++11 version + // struct T: private boost::noncopyable { + // ... + // private: + // T(const T &); + // ... + // }; + // + // // C++11 version + // struct T { + // ... + // private: + // T(const T &) = delete; + // ... + // }; + BOOST_STATIC_CONSTANT(bool, value = ( sizeof(test( - boost::declval::type>() + tt_declval::type*/ const T&>() )) == sizeof(boost::type_traits::yes_type) - || - boost::is_rvalue_reference::value - )); -}; + && + !boost::is_rvalue_reference::value + && !boost::is_array::value + )); + }; -template -struct is_copy_constructible_impl2 { - BOOST_STATIC_CONSTANT(bool, value = false); -}; + template + struct is_copy_constructible_impl2 { + BOOST_STATIC_CONSTANT(bool, value = false); + }; -template -struct is_copy_constructible_impl { + template + struct is_copy_constructible_impl { - BOOST_STATIC_CONSTANT(bool, value = ( - boost::detail::is_copy_constructible_impl2< + BOOST_STATIC_CONSTANT(bool, value = ( + boost::detail::is_copy_constructible_impl2< boost::is_base_and_derived::value, T - >::value - )); -}; + >::value + )); + }; -} // namespace detail + } // namespace detail -template struct is_copy_constructible : public integral_constant::value>{}; -template <> struct is_copy_constructible : public false_type{}; + template struct is_copy_constructible : public integral_constant::value>{}; + template <> struct is_copy_constructible : public false_type{}; #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS -template <> struct is_copy_constructible : public false_type{}; -template <> struct is_copy_constructible : public false_type{}; -template <> struct is_copy_constructible : public false_type{}; + template <> struct is_copy_constructible : public false_type{}; + template <> struct is_copy_constructible : public false_type{}; + template <> struct is_copy_constructible : public false_type{}; #endif } // namespace boost +#endif + #endif // BOOST_TT_IS_COPY_CONSTRUCTIBLE_HPP_INCLUDED diff --git a/test/is_copy_constructible_test.cpp b/test/is_copy_constructible_test.cpp index cbc4030..844f479 100644 --- a/test/is_copy_constructible_test.cpp +++ b/test/is_copy_constructible_test.cpp @@ -80,7 +80,10 @@ TT_TEST_BEGIN(is_copy_constructible) // Main part of the test BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true); -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true); +// Only constructible from has3& not from const-reference, this only works if we have decltype: +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, false); +#endif BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true); BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, false); #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_INTEL_CXX_VERSION) @@ -260,18 +263,9 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true); #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -// Code like `int&& a = 10;` or -// struct nonc { -// nonc() = default; -// nonc(const nonc&) = delete; -// nonc(nonc&&) = delete; -// nonc& operator=(const nonc&) = delete; -// nonc& operator=(nonc&&) = delete; -// }; -// -// nonc && a = nonc(); -// is legal in C++11. so this trait MUST return true. -BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true); +// This is debatable, we used to insist this was true, but copy-constructibility +// implies copying a constant-object, and that isn't the case here: +BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, false); #endif BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_copy_constructible::value, true);