• c++23中的新功能之十七显示this的应用


    一、显式this

    在前面的文章中分析了显式this(Deducing This),具体的内容请移步《c++23新功能之二语法中的Deducing This》,本篇对显式this对实际应用中的一些完善和更新形式进行分析说明,抛砖引玉。

    二、CRTP的应用

    在前面的学习中,学过CRTP(Curiously Recurring Template Pattern ,奇异递归模板模式),其实就是在传统的子继承父的基础上,在利用模板时,将子类传入到父类模板中去的一种转置继承。在前面的文中也对其中的一些用法和特点进行了分析说明。重点是知道了一般这种情况都是在模板的元编程中使用。下面看一下在c++23前后的应用方式的不同情况:

    1、传统方式

    #include 
    template <class T>
    class Base
    {
    public:
        void Display()
        {
            static_cast<T*>(this)->Data();
        }
    
        static void Call()
        {
            T::Call();
        }
    };
    
    class Derived : public Base<Derived>
    {
    public:
        void Data() { std::cout << "Derived function :Data()" << std::endl; };
        static void Call() { std::cout << "Derived function :Call()" << std::endl; };
    };
    int main()
    {
        Derived d;
        Base<Derived> *b = &d;
        b->Display();
        b->Call();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    这个例子非常简单,在前文也出现过。

    2、c++23的应用方式

    class Base
    {
    public:
        template<typename T>
        void Display(this T&&t)
        {
            t->Data();
        }
    };
    
    class Derived : public Base
    {
    public:
        void Data() { std::cout << "Derived function :Data()" << std::endl; };
    };
    int main()
    {
        Derived d;
        Base b;
        b.Display(d);
        //b.(std::move(d));//ok other
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三、在设计模式中的应用

    1、传统方式
    举一个构建者的例子:

    
    template <typename T = void>
    class BuilderOld
    {
        using Derived = std::conditional_t<std::is_void_v<T>, BuilderOld, T>;
    public:
        Derived& owner()
        {
            std::cout << "Builder owner" << std::endl;
            return *static_cast<Derived*>(this);
        }
    
    public:
        Derived& setColor(int color) { std::cout << "color is: "<<color << std::endl; return owner(); }
        Derived& setAge(int age) { std::cout << "age is:"<<age << std::endl; return owner(); }
        Derived& setSex(int sex) { std::cout << "sex is:"<<sex << std::endl; return owner(); }
    };
    
    class DOld :public BuilderOld<DOld>
    {
    public:
        DOld& setLen(int l) { std::cout << "set len is:" <<l<< std::endl; return *this; }
        DOld& setWidth(int w) { std::cout << "set width is:"<<w << std::endl; return *this; }
    };
    
    
    int main()
    {
       BuilderOld<>().setColor(1).setAge(2).setColor(3).setSex(6);//vc
        BuilderOld().setColor(1).setAge(2).setColor(3).setSex(6);//g++
       DOld().setColor(2).setLen(9).setWidth(9).setSex(9);
    
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2、c++23中的应用方式
    在C++23中,使用显式this来对其进行处理:

    class Builder23
    {
    public:
        template <typename T>
        owner& setColor(this T&& t,int color) { std::cout << "set color is:" << color << std::endl; return owner; }
    
        template <typename T>
        owner& setAge(this T&& t,int age) { std::cout << "set age is:" << age << std::endl; return owner; }
    
        template <typename T>
        owner& setSex(this T&& t,int sex) { std::cout << "set sex is:" << sex << std::endl; return owner; }
    };
    
    class D23 :public Builder23
    {
    public:
        D23& setLen(int l) { std::cout << "c++23:set len is:" << l << std::endl; return *this; }
        D23& setWidth( int w) { std::cout << "c++23:set width is:" << w << std::endl; return *this; }
    };
    
    int main()
    {
        Builder23().setColor(1).setAge(9).setColor(11).setSex();
        D23().setColor().setLen().setWidth().setSex();
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在Builder中,不一定非要这种流式调用的方法,其它方法也有很多。重点在于如何真正理解Builder的本身存在的目的。在c++中,实现流式的方法有不少方式,但采用CRTP的方式是一种在编译期处理的情况,这就看具体的需要来决定采用哪种情况了。

    三、总结

    学以致用,用才是关键。学而不用,和不学没有什么区别。具体到计算机的技术上,学而不用,简单来说时间长会忘记,另外一个问题是,计算机技术的迅速更迭,导致形成自身的技术断层,甚至某些技术直接就被淘汰了。这样,再想形成一个完整的知识体系,就非常困难了。同样,也不利于快速的跟进新技术的发展。

  • 相关阅读:
    [iOS开发]事件处理与响应者链
    Cookie和Session
    软考考完了,如何评职称?
    Java和Python中20个基本编程面试问题
    Python 编程基础 | 第二章-基础语法 | 2.1、缩进规则
    JAVA面试题之高级常问必问
    文心一言 vs GPT-4 —— 全面横向比较
    2760.最长奇偶子数组
    ESXI7.0.0升级到ESXI7.0.3
    Kafka的存储机制和可靠性
  • 原文地址:https://blog.csdn.net/fpcc/article/details/133972264