类型特性
类型特性定义一个编译时基于模板的结构,以查询或修改类型的属性。
试图特化定义于 <type_traits> 头文件的模板导致未定义行为,除了 std::common_type 可依照其所描述特化。
定义于<type_traits>头文件的模板可以用不完整类型实例化,除非另外有指定,尽管通常禁止以不完整类型实例化标准库模板。
受支持操作
检查一个类型的对象是否与该类型的指定子对象指针可互转换
std::is_pointer_interconvertible_with_class
template< class S, class M > | (C++20 起) |
给定 S
类型的对象 s
,确定 s.*mp 是否指代 s
的子对象且 s
与其子对象 s.*mp 指针可互转换。若 S
不是完整类型则程序非良构。
若 S
不是标准布局类型 (StandardLayoutType) ,或 M
不是对象类型,或 mp
等于 nullptr,则结果始终为 false。
参数
mp | - | 要检测的成员指针 |
返回值
若 s.*mp 指代 s
的子对象且 s
与其子对象 s.*mp 指针可互转换则为 true,否则为 false,其中 s
是 S
类型的对象。
注解
成员指针表达式 &S::m 的类型并非始终是 M S::*,其中 m
的类型为 M
,因为 m
可能是从 S
的基类继承的成员。可以指定第一模板实参以避免潜在地令人诧异的结果。
若存在 M S::* 类型的值 mp
使得 std::is_pointer_interconvertible_with_class(mp) == true,则 reinterpret_cast<M&>(s) 拥有良定义结果且与 s.*mp 指代同一子对象,其中 s
是合法的 S
类型的左值。
在常用平台上,若 std::is_pointer_interconvertible_with_class(mp) == true,则 mp
的位模式为全零。
功能特性测试宏 | 值 | 标准 | 功能特性 |
---|---|---|---|
__cpp_lib_is_pointer_interconvertible | 201907L | (C++20) | 指针可互换性特征:
|
调用示例
#include <iostream>
#include <type_traits>
namespace std
{
template <typename T, typename C>
struct is_pointer_interconvertible_with_class
{
static constexpr bool value = std::is_convertible<T*, C*>::value &&
std::is_convertible<C*, T*>::value;
};
template<typename T, typename C>
const bool is_pointer_interconvertible_with_class_v =
is_pointer_interconvertible_with_class<C*, T*>::value;
}
class E
{
public:
template<class T> E(T&&) { }
};
class A {};
class B : public A {};
class C {};
class D
{
public:
operator C()
{
return c;
} C c;
};
int main()
{
std::cout << std::boolalpha;
std::cout << "std::is_convertible<A, B>::value: "
<< std::is_convertible<A, B>::value << std::endl;
std::cout << "std::is_convertible<B, A>::value: "
<< std::is_convertible<B, A>::value << std::endl;
std::cout << "std::is_convertible<B*, A*>::value: "
<< std::is_convertible<B*, A*>::value << std::endl;
std::cout << "std::is_convertible<A*, B*>::value: "
<< std::is_convertible<A*, B*>::value << std::endl;
std::cout << "std::is_convertible<B*, C*>::value: "
<< std::is_convertible<B*, C*>::value << std::endl;
std::cout << "std::is_convertible<D, C>::value: "
<< std::is_convertible<D, C>::value << std::endl;
std::cout << "std::is_convertible<E, A>::value: "
<< std::is_convertible<E, A>::value << std::endl;
std::cout << "std::is_convertible<int, double>::value: "
<< std::is_convertible<int, double>::value << std::endl;
std::cout << "std::is_convertible<int, int>::value: "
<< std::is_convertible<int, int>::value << std::endl;
std::cout << "std::is_convertible<int, char>::value: "
<< std::is_convertible<int, char>::value << std::endl;
std::cout << "std::is_convertible<std::string, char>::value:"
<< std::is_convertible<std::string, char>::value << std::endl;
std::cout << "-----------------------------------------------" << std::endl;
std::cout << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<A, B>::value: "
<< std::is_pointer_interconvertible_with_class<A, B>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<B, A>::value: "
<< std::is_pointer_interconvertible_with_class<B, A>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<B*, A*>::value: "
<< std::is_pointer_interconvertible_with_class<B*, A*>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<A*, B*>::value: "
<< std::is_pointer_interconvertible_with_class<A*, B*>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<B*, C*>::value: "
<< std::is_pointer_interconvertible_with_class<B*, C*>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<D, C>::value: "
<< std::is_pointer_interconvertible_with_class<D, C>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<E, A>::value: "
<< std::is_pointer_interconvertible_with_class<E, A>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<int, double>::value: "
<< std::is_pointer_interconvertible_with_class<int, double>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<int, int>::value: "
<< std::is_pointer_interconvertible_with_class<int, int>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<int, char>::value: "
<< std::is_pointer_interconvertible_with_class<int, char>::value << std::endl;
std::cout << "std::is_pointer_interconvertible_with_class<std::string, char>::value:"
<< std::is_pointer_interconvertible_with_class<std::string, char>::value << std::endl;
std::cout << "-----------------------------------------------" << std::endl;
std::cout << std::endl;
return 0;
}
输出
std::is_convertible<A, B>::value: false
std::is_convertible<B, A>::value: true
std::is_convertible<B*, A*>::value: true
std::is_convertible<A*, B*>::value: false
std::is_convertible<B*, C*>::value: false
std::is_convertible<D, C>::value: true
std::is_convertible<E, A>::value: false
std::is_convertible<int, double>::value: true
std::is_convertible<int, int>::value: true
std::is_convertible<int, char>::value: true
std::is_convertible<std::string, char>::value:false
-----------------------------------------------
std::is_pointer_interconvertible_base_of<A, B>::value: false
std::is_pointer_interconvertible_base_of<B, A>::value: false
std::is_pointer_interconvertible_base_of<B*, A*>::value: false
std::is_pointer_interconvertible_base_of<A*, B*>::value: false
std::is_pointer_interconvertible_base_of<B*, C*>::value: false
std::is_pointer_interconvertible_base_of<D, C>::value: false
std::is_pointer_interconvertible_base_of<E, A>::value: false
std::is_pointer_interconvertible_base_of<int, double>::value: false
std::is_pointer_interconvertible_base_of<int, int>::value: true
std::is_pointer_interconvertible_base_of<int, char>::value: false
std::is_pointer_interconvertible_base_of<std::string, char>::value:false
-----------------------------------------------
输出
std::is_convertible<A, B>::value: false
std::is_convertible<B, A>::value: true
std::is_convertible<B*, A*>::value: true
std::is_convertible<A*, B*>::value: false
std::is_convertible<B*, C*>::value: false
std::is_convertible<D, C>::value: true
std::is_convertible<E, A>::value: false
std::is_convertible<int, double>::value: true
std::is_convertible<int, int>::value: true
std::is_convertible<int, char>::value: true
std::is_convertible<std::string, char>::value:false
-----------------------------------------------
std::is_pointer_interconvertible_base_of<A, B>::value: false
std::is_pointer_interconvertible_base_of<B, A>::value: false
std::is_pointer_interconvertible_base_of<B*, A*>::value: false
std::is_pointer_interconvertible_base_of<A*, B*>::value: false
std::is_pointer_interconvertible_base_of<B*, C*>::value: false
std::is_pointer_interconvertible_base_of<D, C>::value: false
std::is_pointer_interconvertible_base_of<E, A>::value: false
std::is_pointer_interconvertible_base_of<int, double>::value: false
std::is_pointer_interconvertible_base_of<int, int>::value: true
std::is_pointer_interconvertible_base_of<int, char>::value: false
std::is_pointer_interconvertible_base_of<std::string, char>::value:false
-----------------------------------------------