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.noexcept.From и To должен каждый быть полным типом, (возможно, cv-квалифицированным) void или массивом с неизвестной границей. Иначе поведение не определено.
Если реализация приведённого выше шаблона прямо или косвенно зависит от неполного типа, и эта реализация могла бы дать другой результат, если бы этот тип был гипотетически завершён, поведение не определено.
Поведение программы, добавляющей специализации для любых шаблонов, описанных на этой странице не определено.
Вспомогательная шаблонная переменная
<tbody> </tbody> template< class From, class To > inline constexpr bool is_convertible_v = is_convertible<From, To>::value; |
(начиная с C++17) | |
template< class From, class To > inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value; |
(начиная с C++20) | |
Унаследован от std::integral_constant
Константы элементы
value [static] |
true, если From преобразуется в To , false иначе (public static константа-элемент) |
Функции-элементы
operator bool |
преобразует объект в bool, возвращает value (public функция-элемент) |
operator() (C++14) |
возвращает value (public функция-элемент) |
Типы элементы
| Тип | Определение |
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 {};
|
Примечание
Даёт чётко определённые результаты для ссылочных типов, типов 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; };
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
// Обратите внимание, что конструктор Идеальной Пересылки делает класс E
// "конвертируемым" из всего. Итак, A можно заменить на 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 = "три";
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("один"s)) << ' '
<< std::quoted(stringify("два"sv)) << ' '
<< std::quoted(stringify(three)) << ' '
<< std::quoted(stringify(42)) << ' '
<< std::quoted(stringify(42.)) << '\n';
}
Вывод:
true false true false true false true "один" "два" "три" "42" "42.000000"
Смотрите также
(C++11) |
проверяет, является ли тип производным от другого типа (шаблон класса) |
| проверяет, является ли тип взаимопреобразуемым по указателю (изначально) базовым классом другого типа (шаблон класса) | |
| проверяет, являются ли объекты типа взаимопреобразуемыми по указателю с указанным подобъектом этого типа (шаблон функции) | |
(C++20) |
указывает, что тип неявно преобразуется в другой тип (концепт) |