【发布时间】:2021-01-04 20:49:55
【问题描述】:
我正在尝试实现自己的 SmartPointer 类,并且在初始工作版本之后,我已经开始改进代码,现在面临一个我无法解决的问题。
这是第一个版本:
template<class T>
class SmartPointer
{
private:
T* ptr;
public:
explicit SmartPointer(T* p = nullptr):ptr(p){}
~SmartPointer(){delete(ptr);}
T& operator*(){return *ptr;}
T* operator->(){return ptr;}
};
我的问题是我必须调用它指定两次,这将是例如。 “int”类型的指针:
SmartPointer<int> intSP(new int());
所以我尝试在 SmartPointer 类的构造函数中创建一个模板构造函数,方法是将其更改为:
template<typename... Args>
explicit SmartPointer(Args... args):ptr(new T(args...)){};
在我提供至少一个参数之前,这可以正常工作。但是当没有提供参数时,整个类开始根本不工作。 (当我从中创建了一个实例并尝试分配一个值时,它会抛出以下错误:“assignment of read-only location '* intSP'”。
所以我试图进一步复杂化它,在参数包的大小上使用 enable_if,不幸的是,结果与前一种情况相同。由于某种原因, enable_if 似乎根本没有做任何事情:
template<typename... Args,
typename = typename std::enable_if<(sizeof...(Args)>0u)>::type>
explicit SmartPointer(Args... args):ptr(new T(args...)){
cout << "constructor with arguments" << endl;
};
template<typename... Args,
typename = typename std::enable_if<(sizeof...(Args)==0u)>::type>
explicit SmartPointer():ptr(new T()){
cout << "constructor without args" << endl;
};
最后是完整的代码,有一些概述:
#include <iostream>
using namespace std;
#define var2str(var) #var
template<class T>
class SmartPointer
{
private:
T* ptr;
public:
template<typename... Args,
typename = typename std::enable_if<(sizeof...(Args)>0u)>::type>
explicit SmartPointer(Args... args):ptr(new T(args...)){
cout << "constructor with arguments" << endl;
};
template<typename... Args,
typename = typename std::enable_if<(sizeof...(Args)==0u)>::type>
explicit SmartPointer():ptr(new T()){
cout << "constructor without arguments" << endl;
};
~SmartPointer(){delete(ptr);}
T& operator*(){return *ptr;}
T* operator->(){return ptr;}
};
int main(int, char**) {
SmartPointer<int> intSP(5);//new int());
cin>>*intSP;
cout << *intSP << " stored in "<< var2str(intSP) << endl;
}
【问题讨论】:
-
你知道deduction guides in C++17怎么用吗?
-
“但是当没有提供参数时,整个类开始根本不工作” - 你确定不是“最令人头疼的解析问题”吗?我的意思是……你写过
SmartPointer<int> intSP();还是SmartPointer<int> intSP{};? -
我读了三次,但无法理解问题所在...请显示MCVE。
-
可能有点离题但最好用:
explicit SmartPointer(Args &&... args) : ptr( new T( forward<Args>( args )... ) ) {}? -
带有
std::enable_if_t<(sizeof...(Args)==0u)>的构造函数是迂腐的UB,因为唯一有效的特化是空包。
标签: c++ variadic-templates sfinae template-specialization parameter-pack