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 test() { return std::declval<From>(); }
is well-formed, (that is, either std::declval<From>()
can be converted to 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.
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) |
value
[static] | true if From is convertible to To , false otherwise (public static member constant) |
operator bool | converts the object to bool, returns value (public member function) |
operator()
(C++14) | returns value (public member function) |
Type | Definition |
---|---|
value_type | bool |
type | std::integral_constant<bool, value> |
(1) is_convertible |
---|
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) > {}; |
(2) is_nothrow_convertible |
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 {}; |
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.
Feature-test macro | Value | Std | Comment |
---|---|---|---|
__cpp_lib_is_nothrow_convertible | 201806L | (C++20) |
std::is_nothrow_convertible |
#include <iomanip> #include <iostream> #include <string> #include <string_view> #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; }; std::cout << std::boolalpha << std::is_convertible_v<B*, A*> << ' ' // true << std::is_convertible_v<A*, B*> << ' ' // false << std::is_convertible_v<D, C> << ' ' // true << std::is_convertible_v<B*, C*> << ' ' // false // Note that the Perfect Forwarding constructor makes the class E be // "convertible" from everything. So, A is replaceable by B, C, D..: << std::is_convertible_v<A, E> << ' '; // true using std::operator "" s, std::operator "" sv; auto stringify = []<typename T>(T x) { if constexpr (std::is_convertible_v<T, std::string> or std::is_convertible_v<T, std::string_view>) return x; else return std::to_string(x); }; const char* three = "three"; std::cout << std::is_convertible_v<std::string_view, std::string> << ' ' // false << std::is_convertible_v<std::string, std::string_view> << ' ' // true << std::quoted(stringify("one"s)) << ' ' << std::quoted(stringify("two"sv)) << ' ' << std::quoted(stringify(three)) << ' ' << std::quoted(stringify(42)) << ' ' << std::quoted(stringify(42.0)) << '\n'; }
Output:
true false true false true false true "one" "two" "three" "42" "42.000000"
(C++11) | checks if a type is derived from the other type (class template) |
(C++20) | checks if a type is a pointer-interconvertible (initial) base of another type (class template) |
(C++20) | checks if objects of a type are pointer-interconvertible with the specified subobject of that type (function template) |
(C++20) | specifies that a type is implicitly convertible to another type (concept) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/types/is_convertible