std::is_convertible, std::is_nothrow_convertible
Defined in header <type_traits>
|
||
template< class From, class To > struct is_convertible; |
(1) | (since C++11) |
template< class From, class To > struct is_nothrow_convertible; |
(2) | (since C++20) |
To
using implicit conversions, or both From
and To
are possibly cv-qualified void
), provides the member constant value
equal to true. Otherwise value
is false. For the purposes of this check, the use of std::declval in the return statement is not considered an odr-use.noexcept
.From
and To
shall each be a complete type, (possibly cv-qualified) void, or an array of unknown bound. Otherwise, the behavior is undefined.
If an instantiation of a template above depends, directly or indirectly, on an incomplete type, and that instantiation could yield a different result if that type were hypothetically completed, the behavior is undefined.
The behavior of a program that adds specializations for any of the templates described on this page is undefined.
Helper variable template
template< class From, class To > inline constexpr bool is_convertible_v = is_convertible<From, To>::value; |
(since C++17) | |
template< class From, class To > inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value; |
(since C++20) | |
Inherited from std::integral_constant
Member constants
value [static] |
true if From is convertible to To , false otherwise (public static member constant) |
Member functions
operator bool |
converts the object to bool, returns value (public member function) |
operator() (C++14) |
returns value (public member function) |
Member types
Type | Definition |
value_type
|
bool
|
type
|
std::integral_constant<bool, value> |
Possible implementation
First version |
---|
namespace detail { template<class T> auto test_returnable(int) -> decltype( void(static_cast<T(*)()>(nullptr)), std::true_type{} ); template<class> auto test_returnable(...) -> std::false_type; template<class From, class To> auto test_implicitly_convertible(int) -> decltype( void(std::declval<void(&)(To)>()(std::declval<From>())), std::true_type{} ); template<class, class> auto test_implicitly_convertible(...) -> std::false_type; } // namespace detail template<class From, class To> struct is_convertible : std::integral_constant<bool, (decltype(detail::test_returnable<To>(0))::value && decltype(detail::test_implicitly_convertible<From, To>(0))::value) || (std::is_void<From>::value && std::is_void<To>::value) > {}; |
Second version |
template<class From, class To> struct is_nothrow_convertible : std::conjunction<std::is_void<From>, std::is_void<To>> {}; template<class From, class To> requires requires { static_cast<To(*)()>(nullptr); { std::declval<void(&)(To) noexcept>()(std::declval<From>()) } noexcept; } struct is_nothrow_convertible<From, To> : std::true_type {}; |
Notes
Gives well-defined results for reference types, void types, array types, and function types.
Currently the standard has not specified whether the destruction of the object produced by the conversion (either a result object or a temporary bound to a reference) is considered as a part of the conversion. This is LWG issue 3400.
All known implementations treat the destruction as a part of the conversion, as proposed in P0758R1.
Example
#include <iostream> #include <type_traits> class E { public: template<class T> E(T&&) { } }; int main() { class A {}; class B : public A {}; class C {}; class D { public: operator C() { return c; } C c; }; bool b2a = std::is_convertible<B*, A*>::value; bool a2b = std::is_convertible<A*, B*>::value; bool b2c = std::is_convertible<B*, C*>::value; bool d2c = std::is_convertible<D, C>::value; // A Perfect Forwarding constructor make the class 'convert' from everything bool everything2e = std::is_convertible<A, E>::value; //< B, C, D, etc std::cout << std::boolalpha; std::cout << b2a << '\n'; std::cout << a2b << '\n'; std::cout << b2c << '\n'; std::cout << d2c << '\n'; std::cout << '\n'; std::cout << everything2e << '\n'; }
Output:
true false false true true