(新手观点,大佬轻喷)
目前版本的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
~~~