std::is_convertible, std::is_nothrow_convertible
Определено в заголовочном файле <type_traits> | ||
|---|---|---|
template< class From, class To > struct is_convertible; | (1) | (начиная с C++11) |
template< class From, class To > struct is_nothrow_convertible; | (2) | (начиная с C++20) |
To test() { return std::declval<From>(); } корректно (то есть если std::declval<From>() можно преобразовать в To с помощью неявных преобразований либо если и From, и To могут быть cv-квалифицированным void), предоставляет константу-член value, равную true. В противном случае value равно false. Для целей этой проверки использование std::declval в операторе return не считается ODR-использованием. | Если | (начиная с C++26) |
Если From или To не является полным типом, (возможно, cv-квалифицированным) void или массивом неизвестной границы, поведение не определено.
Если инстанцирование шаблона выше прямо или косвенно зависит от неполного типа и это инстанцирование могло бы дать другой результат, если бы этот тип гипотетически был полным, поведение не определено.
Если программа добавляет специализации для любого из шаблонов, описанных на этой странице, поведение не определено.
Вспомогательный шаблон переменной
template< class From, class To > constexpr bool is_convertible_v = is_convertible<From, To>::value; | (начиная с C++17) | |
template< class From, class To > constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value; | (начиная с C++20) |
Наследуется от std::integral_constant
Константы-члены
|
value
[static] |
true, если From преобразуем в To, иначе false (общедоступная статическая константа-член) |
Функции-члены
|
operator bool | преобразует объект в bool, возвращает value (общедоступная функция-член) |
|
operator()
(C++14) | возвращает value (общедоступная функция-член) |
Типы-члены
| Тип | Определение |
|---|---|
value_type | bool |
type | std::integral_constant<bool,value> |
Возможная реализация
is_convertible (1) |
|---|
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)
> {};
|
is_nothrow_convertible (2) |
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 {};
|
Примечания
Дает корректные результаты для ссылочных типов, типов void, типов массивов и типов функций.
В настоящее время стандарт не уточняет, считается ли уничтожение объекта, созданного в результате преобразования (объекта результата или временного объекта, привязанного к ссылке), частью преобразования. Это вопрос LWG 3400.
Все известные реализации считают уничтожение частью преобразования, как предложено в P0758R1.
| Макрос проверки наличия функциональности | Значение | Стандарт | Функциональность |
|---|---|---|---|
__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; };
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';
}
Вывод:
"one" "two" "three" "42" "42.000000"
См. также
|
(C++11) | проверяет, является ли один тип базовым для другого типа (шаблон класса) |
|
(C++20) | проверяет, является ли тип взаимно преобразуемой по указателю (начальной) базой другого типа (шаблон класса) |
|
(C++20) | проверяет, являются ли объекты типа взаимно преобразуемыми по указателю с указанным подобъектом этого типа (шаблон функции) |
|
(C++20) | задает требование, согласно которому тип неявно преобразуется в другой тип (концепт) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/types/is_convertible