Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -1549,6 +1549,40 @@ = is_convertible<_From, _To>::value; #endif +// is_nothrow_convertible + +#if _LIBCPP_STD_VER > 17 + +template +struct __is_nothrow_convertible_helper +{ +private: + template + static void __test_noexcept(_Tp) noexcept; + + template + static bool_constant(declval<__Fm>()))> + __test(int); + + template + static false_type + __test(...); + +public: + using type = decltype(__test<_Fm, _To>(0)); +}; + +template +struct is_nothrow_convertible : __or_< + __and_, is_void<_Fm>>, + __and_, __is_nothrow_convertible_helper<_Fm, _To>> +>::type { }; + +template +inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_Fm, _To>::value; + +#endif // _LIBCPP_STD_VER > 17 + // is_empty #if __has_feature(is_empty) || (_GNUC_VER >= 407) Index: test/std/type_traits/is_nothrow_convertible.pass.cpp =================================================================== --- /dev/null +++ test/std/type_traits/is_nothrow_convertible.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include + +#include "test_macros.h" + +struct A {}; +struct B { +public: + operator A() { return a; } A a; +}; + +class C { }; +class D { +public: + operator C() noexcept { return c; } C c; +}; + +int main(int, char**) { + static_assert((std::is_nothrow_convertible::value), ""); + static_assert(!(std::is_nothrow_convertible::value), ""); + + static_assert(!(std::is_nothrow_convertible::value), ""); + static_assert((std::is_nothrow_convertible::value), ""); + + static_assert((std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert((std::is_nothrow_convertible_v), ""); + + static_assert((std::is_nothrow_convertible_v), ""); + static_assert((std::is_nothrow_convertible_v), ""); + static_assert((std::is_nothrow_convertible_v), ""); + static_assert((std::is_nothrow_convertible_v), ""); + + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + + typedef void V(); + typedef int I(); + static_assert(!(std::is_nothrow_convertible_v), ""); + static_assert(!(std::is_nothrow_convertible_v), ""); + + return 0; +}