首页 > 编程语言 >C++标准模板(STL)- 概念库 (C++20) - 指定一个类型派生自另一类型 - (std::derived_from)

C++标准模板(STL)- 概念库 (C++20) - 指定一个类型派生自另一类型 - (std::derived_from)

时间:2024-07-21 22:30:03浏览次数:18  
标签:std false derived value base C++ 20 convertible

概念库提供基础语言概念的定义,它们能用于进行模板实参的编译时校验,以及基于类型属性的函数派发。这些概念在程序中提供等式推理的基础。

标准库中的大多数概念一同加上了语法及语义要求。通常,编译器只能检查语法要求。若在使用点语义要求未得到满足,则程序为病式,不要求诊断。

类型支持(基本类型、RTTI、类型特性)

指定一个类型派生自另一类型

std::derived_from

定义于头文件 <concepts>

template< class Derived, class Base >

concept derived_from =
  std::is_base_of_v<Base, Derived> &&

  std::is_convertible_v<const volatile Derived*, const volatile Base*>;
(C++20 起)

概念 derived_from<Derived, Base> 若且唯若忽略 cv 限定符后 Base 是类类型,且它为 Derived 或是 Derived 的公开无歧义基类才得到满足。

注意当 BaseDerived 的私有或受保护基类时,此行为异于 std::is_base_of

参阅

is_base_of

(C++11)

检查一个类型是否派生自另一个类型
(类模板)

is_convertibleis_nothrow_convertible

(C++11)(C++20)

检查是否能转换一个类型为另一类型
(类模板)

调用示例 (c++11) 

#include <iostream>
#include <type_traits>

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;
};


//自定义的实现
namespace std
{
template< class Derived, class Base >
constexpr bool derived_from =
    ((std::is_base_of<Base, Derived>::value) &&
     (std::is_convertible<const volatile Derived*, const volatile Base*>::value));
}

int main()
{
    std::cout << std::boolalpha;

    std::cout << "std::is_base_of<B, A>::value:       "
              << std::is_base_of<B, A>::value << std::endl;
    std::cout << "std::is_base_of<A, B>::value:       "
              << std::is_base_of<A, B>::value << std::endl;
    std::cout << "std::is_base_of<B*, A*>::value:       "
              << std::is_base_of<B*, A*>::value << std::endl;
    std::cout << "std::is_base_of<A*, B*>::value:       "
              << std::is_base_of<A*, B*>::value << std::endl;
    std::cout << "std::is_base_of<B*, C*>::value:       "
              << std::is_base_of<B*, C*>::value << std::endl;
    std::cout << "std::is_base_of<D, C>::value:         "
              << std::is_base_of<D, C>::value << std::endl;
    std::cout << "std::is_base_of<int, double>::value:  "
              << std::is_base_of<int, double>::value << std::endl;
    std::cout << "std::is_base_of<int, char>::value:    "
              << std::is_base_of<int, char>::value << std::endl;
    std::cout << "std::is_base_of<std::string, char>::value:    "
              << std::is_base_of<std::string, char>::value << std::endl;

    // 完美转发构造函数使类能从任何类型转换
    std::cout << "std::is_base_of<A, E>::value:         "
              << std::is_base_of<A, E>::value << std::endl;
    std::cout << "-----------------------------------------------" << std::endl;
    std::cout << 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*, 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<int, double>::value:  "
              << std::is_convertible<int, double>::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::is_convertible<A, E>::value:         "
              << std::is_convertible<A, E>::value << std::endl;
    std::cout << "-----------------------------------------------" << std::endl;
    std::cout << std::endl;

    std::cout << "std::derived_from<B, A>:       "
              << std::derived_from<B, A> << std::endl;
    std::cout << "std::derived_from<A, B>:       "
              << std::derived_from<A, B> << std::endl;
    std::cout << "std::derived_from<B*, A*>:       "
              << std::derived_from<B*, A*> << std::endl;
    std::cout << "std::derived_from<A*, B*>:       "
              << std::derived_from<A*, B*> << std::endl;
    std::cout << "std::derived_from<B*, C*>:       "
              << std::derived_from<B*, C*> << std::endl;
    std::cout << "std::derived_from<D, C>:         "
              << std::derived_from<D, C> << std::endl;
    std::cout << "std::derived_from<int, double>:  "
              << std::derived_from<int, double> << std::endl;
    std::cout << "std::derived_from<int, char>:    "
              << std::derived_from<int, char> << std::endl;
    std::cout << "std::derived_from<std::string, char>:    "
              << std::derived_from<std::string, char> << std::endl;

    // 完美转发构造函数使类能从任何类型转换
    std::cout << "std::derived_from<A, E>:         "
              << std::derived_from<A, E> << std::endl;

    return 0;
}

输出

std::is_base_of<B, A>::value:       false
std::is_base_of<A, B>::value:       true
std::is_base_of<B*, A*>::value:       false
std::is_base_of<A*, B*>::value:       false
std::is_base_of<B*, C*>::value:       false
std::is_base_of<D, C>::value:         false
std::is_base_of<int, double>::value:  false
std::is_base_of<int, char>::value:    false
std::is_base_of<std::string, char>::value:    false
std::is_base_of<A, E>::value:         false
-----------------------------------------------

std::is_convertible<B, A>::value:       true
std::is_convertible<A, B>::value:       false
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<int, double>::value:  true
std::is_convertible<int, char>::value:    true
std::is_convertible<std::string, char>::value:    false
std::is_convertible<A, E>::value:         true
-----------------------------------------------

std::derived_from<B, A>:       true
std::derived_from<A, B>:       false
std::derived_from<B*, A*>:       false
std::derived_from<A*, B*>:       false
std::derived_from<B*, C*>:       false
std::derived_from<D, C>:         false
std::derived_from<int, double>:  false
std::derived_from<int, char>:    false
std::derived_from<std::string, char>:    false
std::derived_from<A, E>:         false

标签:std,false,derived,value,base,C++,20,convertible
From: https://blog.csdn.net/qq_40788199/article/details/140423903

相关文章

  • 2024年steam好玩的新游:《哈迪斯2》《雨中冒险: 回归》等
    今天已经有不少新游上线,下面为大家整理了2024年好玩的steam游戏,一起来看看。2024值得一玩的新游1、《哈迪斯2》哈迪斯2(HadesII)是SupergiantGames继其广受好评的作品《哈迪斯》之后开发的一款动作角色扮演游戏。在《哈迪斯》中,玩家扮演冥王哈迪斯的儿子扎格列欧斯,试图逃......
  • C++11(2): 通用
    31.继承构造函数structB:A{usingA::A;};32.委派构造函数classA{public: A() :A(1234){}//先调用A(int) A(intn1):A(n1,'C'){}//先调用A(int,char) A(charc1):A(2,c1){}//先调用A(int,char)private: A(intn2,charc2):my_......
  • HDU多校 2024R1
    T1把\(A\)的所有循环位移哈希一下扔set里,拿\(B\)的所有长为\(|A|\)的子串查一遍即可。代码#include<iostream>#include<set>usingnamespacestd;set<unsignedlonglong>st;constintB=2333;unsignedlonglongpw[2000005];intmain(){inttc;......
  • c++ 引用和指针
      c++引用和指针在C++中,引用和指针是两个非常重要的概念,它们有一些相似之处也有一些不同之处。相似之处:引用和指针都可以指向一个对象。引用一旦被初始化指向一个对象后,就不能再指向其他对象,而指针可以在任何时候指向其他对象。不同之处:引用在......
  • 快速完成VsCode C/C++开发环境配置
    前言本人在配置VsCodeC++开发环境时,查看了很多的博客,内容参差不齐,尤其是关于json文件的配置,绕的人头很晕,最终还是通过阅读官方文档,结合部分博客的指引,完成了环境的配置,在此记录本人的配置过程,希望能帮助到大家。事先声明,本文的内容大量引自VsCode官方的文章:https://code.visual......
  • P2704 [NOI2001] 炮兵阵地
    原题链接题解经典的状压dpcode#include<bits/stdc++.h>#definelllonglong#definelowbit(x)((x)&(-x))usingnamespacestd;intsit[105];intdp[505][505][4];boolcheck(intx){intx1=(x>>1)>>1;intx2=(x<<1)<<1;......
  • OpenCV 遍历Mat,像素操作,使用TrackBar 调整图像的亮度和对比度 C++实现
    文章目录1.使用C++遍历Mat,完成颜色反转1.1常规遍历方式1.2迭代器遍历方式1.3指针访问方式遍历(最快)1.4不同遍历方式的时间对比2.图像像素操作,提高图像的亮度3.TrackBar进度条操作3.1使用TrackBar调整图像的亮度3.2使用TrackBar调整图像的对比度1.使用C++遍历M......
  • 2024暑假集训测试7
    前言比赛链接。终于不挂分了这次,但是T2写得太慢了导致T4没写完只能胡暴力。但是赛时数据和样例出了好多问题给不少人造成了影响。T1abc猜想\(ans=\lfloor\dfrac{a^b}{c}\rfloor\bmodc=\dfrac{a^b-a^b\bmodc}{c}\bmodc\)不妨设\(\dfrac{a^b-a^b\bmodc}{c}=kc+a......
  • 2024 洛谷月赛(柒)
    月赛GGrun%%%T1在相思树下I签到题QWQ,找规律易得。证明未知每次一定会删掉一半的数,所以第\(i\)次操作都会提供一个\(1<<i-1\)的贡献。这个贡献就是下一次会往后跳多少个位置。假如一开始确定留下的是第一个,那删偶数不会有影响,而删奇数需要往后跳。code#include<bit......
  • C++吃豆人~
    #include<cstdio>#include<iostream>#include<ctime>#include<conio.h>#include<windows.h>#include<cstdlib>#include<cstring>usingnamespacestd;constintn=809;structPoint{intx,y;};intdali;intfx[......