0
votes

Given that I have a forward declared type:

class Foo;

I want to make a unique_ptr to this type:

unique_ptr<Foo> pFoo;

This works fine in but I can't make it work in .

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 of Foo
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1149) : while compiling class template member function void 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 instantiation void 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 instantiation std::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 instantiation std::is_empty<_Ty> being compiled
with
[
_Ty=std::default_delete
]
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(63) : see reference to class template instantiation std::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 type Foo; no destructor called (....\src\STETestbed\STETestbed.cpp)
O:\Engine\stetestbed\include\STETestbed\ComponentDirector.h(26) : see declaration of Foo

Was there a workaround for that back in the dark ages, or can I just not forward declare?

1
Is pFoo a member or a variable? Also, if visual studio 2012s standard library is not C++11 compliant, could you use boost::scoped_ptr instead?Artyer
@Artyer pFoo is a member. I haven't included Boost in this project, and I think I'd surrender my forward declaration long before I did. VS2012 does support unique_ptr but yeah, it seems like it is not fully supported.Jonathan Mee
Is the destructor of the class containing pFoo implemented in the header or in the .cpp? (Defaulted/not user-declared counts as "in the header".) If the former is the case, try the latter.Max Langhof
@MaxLanghof Tried both, neither worked for me :(Jonathan Mee
You might try to provide specific Deleter which doesn't requires complete class from declaration.Jarod42

1 Answers

0
votes

As mentioned by Jarod42 The problem seems to be that the default_deleter implemented by required a complete type on declaration. Latter versions of 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;
}

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 : a member of a class template cannot acquire a function type

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

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>))