std::is_convertible, std::is_nothrow_convertible
Min standard notice:
Header: <type_traits>
- If the imaginary function definition To test() { return std::declval
(); } is well-formed, (that is, either std::declval () 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. If To is a reference type and a temporary object would be created when binding std::declval () to To, the return statement in the imaginary function is considered well-formed, even though such binding is ill-formed in an actual function. (since C++26)
# Declarations
template< class From, class To >
struct is_convertible;
(since C++11)
template< class From, class To >
struct is_nothrow_convertible;
(since C++20)
# 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 <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; };
static_assert(std::is_convertible_v<B*, A*>);
static_assert(!std::is_convertible_v<A*, B*>);
static_assert(std::is_convertible_v<D, C>);
static_assert(!std::is_convertible_v<B*, C*>);
// Note that the Perfect Forwarding constructor makes the class E be
// "convertible" from everything. So, A is replaceable by B, C, D..:
static_assert(std::is_convertible_v<A, E>);
static_assert(!std::is_convertible_v<std::string_view, std::string>);
static_assert(std::is_convertible_v<std::string, std::string_view>);
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);
};
using std::operator "" s, std::operator "" sv;
const char* three = "three";
std::cout << std::quoted(stringify("one"s)) << ' '
<< std::quoted(stringify("two"sv)) << ' '
<< std::quoted(stringify(three)) << ' '
<< std::quoted(stringify(42)) << ' '
<< std::quoted(stringify(42.0)) << '\n';
}