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 в операторе возврата не считается odr-использованием.noexcept.From и To должны быть полными типами (возможно, cv-квалифицированными), void или массивом неизвестной длины. В противном случае поведение не определено.
Если экземпляр шаблона выше зависит, прямо или косвенно, от неполного типа, и этот экземпляр мог бы дать другой результат, если бы этот тип был гипотетически завершён, поведение не определено.
Поведение программы, добавляющей специализации для любого из описанных на этой странице шаблонов, не определено.
Вспомогательный шаблон переменной
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 в противном случае (общедоступная статическая член-константа) |
Члены-функции
| operator bool | преобразует объект в bool, возвращает value (общедоступная член-функция) |
| operator()
(C++14) | возвращает value (общедоступная член-функция) |
Типы членов
| Тип | Определение |
|---|---|
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.
| Макрос проверки наличия функции | Значение | Std | Функция |
|---|---|---|---|
__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';
}Вывод:
true false true false true false true "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/w/cpp/types/is_convertible