我被困在 C++03 编译器中,并试图从(智能指针)模板类中消除“void”类型的函数。
MRE(从课堂上删除所有非必要信息):
template<typename T> struct EnableIfNotVoid { typedef T type; };
template<> struct EnableIfNotVoid<void> {};
template<typename T> class SmartPtr
{
public:
template<typename U = T>
typename EnableIfNotVoid<U>::type &operator *(void) const
{
return *content;
}
private:
T* content;
};
int main(int, char **)
{
SmartPtr<int> works;
SmartPtr<void> noWork;
int& i = *works;
}
当通过 C++11 编译器运行它时(我不需要开始类),它可以完美地工作,但是当我尝试使用 C++03 编译器编译它时,我陷入困境,我得到了错误
default template arguments may not be used in function templates
。
我尝试过的其他事情(以及编译器抛出的错误):
没有默认参数:
no match for 'operator*' in '*works'
template<typename U>
typename EnableIfNotVoid<U>::type &operator *(void) const
{
return content;
}
无模板:
no type named 'type' in 'struct EnableIfNotVoid<void>'
typename EnableIfNotVoid<T>::type &operator *(void) const
{
return content;
}
没有 SFINAE(为了完整起见):
forming reference to void
T &operator *(void) const
{
return *content;
}
我想避免必须专门化整个类(相当大),只是为了“省略”两个小函数,如果有一些更聪明的方法来做到这一点,我会非常感激。
与稍微扩展的专业助手一起接近。
#include <boost/static_assert.hpp>
template<typename T>
struct SmartPtrImpl
{
typedef T & Reference;
template<typename Dummy>
static Reference Deref(T * ptr)
{
return * ptr;
}
};
template<>
struct SmartPtrImpl<void>
{
typedef void Reference;
template<typename Dummy>
static Reference Deref(void *)
{
BOOST_STATIC_ASSERT_MSG((0 == sizeof(Dummy)), "SmartPtr<void> does not support dereference");
return;
}
};
template<typename T>
class SmartPtr
{
public: typedef SmartPtrImpl<T> Impl;
protected: T * m_ptr;
public: SmartPtr(void): m_ptr() {}
public: typename Impl::Reference
operator *(void) const
{
return Impl::template Deref<int>(m_ptr);
}
// other stuff...
};
int main()
{
SmartPtr<int> works; *works;
SmartPtr<void> noWork; // *noWork;
}
取消注释
// *noWork;
会触发静态断言:
错误:“sizeof”对不完整类型“boost::STATIC_ASSERTION_FAILURE”的无效应用
23 | 23 BOOST_STATIC_ASSERT_MSG((0 == sizeof(Dummy)), "SmartPtr 不支持取消引用");