Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

对construct的可变参数模板进行更新 #124

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Commits on Jan 15, 2023

  1. 对construct的可变参数模板进行更新

    (新手观点,大佬轻喷)
    目前版本的construct的可变参数模板版本并不能有效地让自定义类通过construct来创建对象,如:
    对于如下代码:
    ~~~
    #include<iostream>
    #include"allocator.h"
    using namespace std;
    class A{
    public:
        A(int a):m(a),n(0.0){
            cout<<"int constructor"<<endl;
        }
        A(int a,double b):m(a),n(b){
            cout<<"int and double constructor"<<endl;
        }
        int m;
        double n;
    };
    
    int main(){
    	mstl::allocator<A> a;
    	A* p1=a.allocate(10);
    	a.construct(p1,10);//construct的模板参数包匹配的类型为int,相当于construct(A*,int && args)
    	a.construct(p1,10,1.0);//相当于construct(A*,int &&,double &&),此时无法调用自己写的forward
    	a.deallocate(p1);
    	
    	return 0;
    }
    ~~~
    
    如果construct.h中存在
    
    template<typename T,typename ...Args>
    void construct(T* ,Args && ...args),那么会导致a.construct(p1,10)无法正确匹配到util.h中的construct(Ty1 *,const Ty2&value),a.construct(p1,10,1.0)会报no matching function的错误
    如果将上述代码从construct.h中删掉,那么第20行代码会调用A(int)构造函数,打印出"int constructor"
    第21行代码则会因为没有对应版本的forward\<T\>而报错
    但是std::allocator是可以实现上述功能的:
    ~~~
    #include<iostream>
    #include"allocator.h"
    using namespace std;
    class A{
    public:
        A(const int& a):m(a),n(0.0){
            cout<<"int constructor"<<endl;
        }
        A(int && a):m(mstl::move(a)),n(0.0){
            cout<<"int move constructor"<<endl;
        }
        A(const int& a,const double &b):m(a),n(b){
            cout<<"int and double constructor"<<endl;
        }
        int m;
        double n;
    };
    
    int main(){
    	allocator<A> a;
    	A* p1=a.allocate(10);
        int b=10;
    	a.construct(p1,20);//打印"int constructor"
    	a.construct(p1,10,1.0);//打印"int and double constructor"
    	cout<<p1->m<<endl;//10
        a.deallocate(p1,10);
    	
    	return 0;
    }
    ~~~
    
    通过调试,发现上述代码在执行到construct(p1,10,0.1)时,跳转到了new_allocator.h里的construct可变参数模板:
    
    ![image-20230114233907408](C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20230114233907408.png)
    
    解决方法:
    
    在/allocator.h的allocator结构体内部的construct()直接使用::new分配空间和调用对象的构造函数,
    
    ~~~
    template<class T>
    template<typename Other,typename ... Args>
    void allocator<T>::construct(Other* p,Args && ... args){
    	::new ((void*)p) Other(mstl::forward<Args>(args)...);
    }
    ~~~
    
    事实上,无需提供三个版本的construct()(通过调用util.h里的重载的construct函数),在allocator里仅需一个上述的construct可变参数模板,也可以满足很多情况的使用:
    
    ~~~
    ...
    int main(){
    
        mstl::allocator<A> a;/《?》
    	A* p1=a.allocate(10);
    	a.construct(p1,10);//int move constructor
    	a.construct(p1,10,1.0);//int and double constructor
        int n1=10;
        double n2=2.0;
    	a.construct(p1,n1,n2);//int and double constructor
    	a.deallocate(p1,10);
    	return 0;
    }
    执行结果如下:
    int move constructor
    int and double constructor
    int and double constructor
    ~~~
    David1West committed Jan 15, 2023
    Configuration menu
    Copy the full SHA
    5587cbf View commit details
    Browse the repository at this point in the history