模板中的可变参数模板函数特化 class
Variadic template function specialization in a template class
我正在尝试实现自己的 SmartPointer class,在初始工作版本之后,我开始改进代码,但现在遇到一个我无法解决的问题。
这是第一个版本:
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 class 的构造函数中创建一个模板构造函数,方法是将其更改为:
template<typename... Args>
explicit SmartPointer(Args... args):ptr(new T(args...)){};
在我提供至少一个参数之前,它工作正常。但是当没有提供参数时,整个 class 开始根本不起作用。 (当我从它创建一个实例并尝试分配一个值时,它抛出以下错误:“分配只读位置'* 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;
}
我想你的问题(只有一个构造函数)是由“令人烦恼的解析”引起的(here 对“最令人烦恼的解析问题”的描述,该问题的一个更壮观的版本)。
我的意思是...如果你写
SmartPointer<int> intSP();
编译器将其解释为函数声明。
如果你想初始化一个没有参数的变量,你可以使用方括号
SmartPointer<int> intSP{};
或没有括号
SmartPointer<int> intSP;
我想下面的例子应该有用
#include <iostream>
template <typename T>
class SmartPointer
{
private:
T * ptr;
public:
template <typename... Args>
explicit SmartPointer (Args && ... args)
: ptr{ new T{ std::forward<Args>(args)... } }
{ }
~SmartPointer ()
{ delete(ptr); }
T & operator* ()
{ return *ptr; }
T * operator-> ()
{ return ptr; }
};
int main ()
{
SmartPointer<int> intSP1; // OK
//SmartPointer<int> intSP2(); // Error: vexing parse
SmartPointer<int> intSP3{}; // OK
SmartPointer<int> intSP4{5}; // OK
SmartPointer<int> intSP5(5); // OK (no more vexing parse)
}
我正在尝试实现自己的 SmartPointer class,在初始工作版本之后,我开始改进代码,但现在遇到一个我无法解决的问题。
这是第一个版本:
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 class 的构造函数中创建一个模板构造函数,方法是将其更改为:
template<typename... Args>
explicit SmartPointer(Args... args):ptr(new T(args...)){};
在我提供至少一个参数之前,它工作正常。但是当没有提供参数时,整个 class 开始根本不起作用。 (当我从它创建一个实例并尝试分配一个值时,它抛出以下错误:“分配只读位置'* 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;
}
我想你的问题(只有一个构造函数)是由“令人烦恼的解析”引起的(here 对“最令人烦恼的解析问题”的描述,该问题的一个更壮观的版本)。
我的意思是...如果你写
SmartPointer<int> intSP();
编译器将其解释为函数声明。
如果你想初始化一个没有参数的变量,你可以使用方括号
SmartPointer<int> intSP{};
或没有括号
SmartPointer<int> intSP;
我想下面的例子应该有用
#include <iostream>
template <typename T>
class SmartPointer
{
private:
T * ptr;
public:
template <typename... Args>
explicit SmartPointer (Args && ... args)
: ptr{ new T{ std::forward<Args>(args)... } }
{ }
~SmartPointer ()
{ delete(ptr); }
T & operator* ()
{ return *ptr; }
T * operator-> ()
{ return ptr; }
};
int main ()
{
SmartPointer<int> intSP1; // OK
//SmartPointer<int> intSP2(); // Error: vexing parse
SmartPointer<int> intSP3{}; // OK
SmartPointer<int> intSP4{5}; // OK
SmartPointer<int> intSP5(5); // OK (no more vexing parse)
}