将 unique_ptr 设为前向声明类型的解决方法 [英] Workaround for Making a unique_ptr to a Forward Declared Type
问题描述
鉴于我有一个转发声明类型:
class Foo;
我想制作一个 unique_ptr
到这种类型:
I want to make a unique_ptr
to this type:
unique_ptr<Foo> pFoo;
这在 visual-studio-2017 但我不能让它在 visual-studio-2012.
This works fine in visual-studio-2017 but I can't make it work in visual-studio-2012.
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1150): error C2027: use of undefined type Foo
(....\src\STETestbed\STETestbed.cpp)
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(26) :参见 Foo
的声明C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1149) : while 编译类模板成员函数 void std::default_delete<_Ty>::operator ()(_Ty *) throw() 常量
与
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1444) :参见对函数模板实例化的引用 void std::default_delete<_Ty>::operator ()(_Ty *) throw() const
正在编译
与
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\type_traits(743) :参见正在编译的类模板实例std::default_delete<_Ty>
的参考
与
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1281) :请参阅对正在编译的类模板实例化std::is_empty<_Ty>
的引用
与
[
_Ty=std::default_delete
]
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(63) :参见正在编译的类模板实例std::unique_ptr<_Ty>
的参考
与
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1151):错误 C2338:无法删除不完整的类型 (....\src\STETestbed\STETestbed.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1152):警告 C4150:删除指向不完整类型 Foo
的指针;没有调用析构函数 (....\src\STETestbed\STETestbed.cpp)
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(26) :参见 Foo
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1150): error C2027: use of undefined type
Foo
(....\src\STETestbed\STETestbed.cpp)
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(26) : see declaration ofFoo
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1149) : while compiling class template member functionvoid std::default_delete<_Ty>::operator ()(_Ty *) throw() const
with
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1444) : see reference to function template instantiationvoid std::default_delete<_Ty>::operator ()(_Ty *) throw() const
being compiled
with
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\type_traits(743) : see reference to class template instantiationstd::default_delete<_Ty>
being compiled
with
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1281) : see reference to class template instantiationstd::is_empty<_Ty>
being compiled
with
[
_Ty=std::default_delete
]
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(63) : see reference to class template instantiationstd::unique_ptr<_Ty>
being compiled
with
[
_Ty=Foo
]
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1151): error C2338: can't delete an incomplete type (....\src\STETestbed\STETestbed.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1152): warning C4150: deletion of pointer to incomplete typeFoo
; no destructor called (....\src\STETestbed\STETestbed.cpp)
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(26) : see declaration ofFoo
在黑暗时代是否有解决方法,或者我可以不提前声明?
Was there a workaround for that back in the dark ages, or can I just not forward declare?
推荐答案
正如 Jarod42 提到的 问题似乎是 visual-studio-2012 需要完整的类型声明. visual-studio<的后期版本/a> 只需要调用括号运算符时的完整类型.
As mentioned by Jarod42 The problem seems to be that the default_deleter
implemented by visual-studio-2012 required a complete type on declaration. Latter versions of visual-studio only required the complete type at the point the parenthesis operator is called.
我们可以通过提供一个函子来解决这个问题,它提供了一个不需要声明完整类型的删除器:
We can work around this by providing a functor which provides a deleter which does not require the complete type on declaration:
template <typename T>
void custom_deleter(T* param) {
delete param;
}
要使用 custom_deleter
作为模板参数,我们需要将它变成一个函子,否则编译器会出错:
To use custom_deleter
as a template parameter we'll need to make it into a functor otherwise the compiler will error:
error C2207: std::_Unique_ptr_base<_Ty,_Dx,_Empty_deleter>::_Mydel
: 类模板的成员无法获取函数类型
error C2207:
std::_Unique_ptr_base<_Ty,_Dx,_Empty_deleter>::_Mydel
: a member of a class template cannot acquire a function type
因此,在 Foo
前向声明的标头中,我们需要将 unique_ptr
定义为:
So in the header where Foo
is forward declared we'll need to define the unique_ptr
as:
unique_ptr<Foo, function<void(Foo*)>> pFoo
在定义了 Foo
的实现文件中,我们需要将其赋值为:
And in the implementation file where Foo
is defined we'll need to assign it as:
pFoo = decltype(pFoo)(new Foo, std::function<void(Foo*)>(custom_deleter<Foo>))
这篇关于将 unique_ptr 设为前向声明类型的解决方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!