Reputation: 4505
I have
template<typename T>
class queue
{
private:
struct node
{
T data;
std::unique_ptr<node> next; //compile error on incomplete type
node(T&& data_):
data(std::move(data_))
{}
};
std::unique_ptr<node> head;
node* tail;
public:
queue():
tail(nullptr)
{}
I get compile error on marked line in VS10. Shouldn't I be allowed to use an incomplete type in this case (instantiate the template - the constructor - here for int as an example) ? Is there a work-around ?
EDIT
singlethreadedqueue.h(62): error C2079: 'queue<T>::node::next' uses undefined class 'std::unique_ptr<_Ty>'
1> with
1> [
1> T=MyClass
1> ]
1> and
1> [
1> _Ty=queue<MyClass>::node
1> ]
1> c:\program files\microsoft visual studio 10.0\vc\include\memory(2161) : see reference to class template instantiation 'queue<T>::node' being compiled
1> with
1> [
1> T=MyClass
1> ]
1> c:\program files\microsoft visual studio 10.0\vc\include\memory(2195) : see reference to class template instantiation 'std::_Unique_ptr_base<_Ty,_Dx,_Empty_deleter>' being compiled
1> with
1> [
1> _Ty=queue<MyClass>::node,
1> _Dx=std::default_delete<queue<MyClass>::node>,
1> _Empty_deleter=true
1> ]
1> singlethreadedqueue.h(69) : see reference to class template instantiation 'std::unique_ptr<_Ty>' being compiled
1> with
1> [
1> _Ty=queue<MyClass>::node
1> ]
1> : see reference to class template instantiation 'queue<T>' being compiled
1> with
1> [
1> T=MyClass
1> ]
Upvotes: 5
Views: 3053
Reputation: 523184
The requirement of complete type at the template instantiation point is due to std::default_delete
, so probably you could work-around it by providing a custom deleter.
struct node; // node_delete need to know 'node' is a type.
struct node_deleter
{ // std::unique_ptr needs 'node_deleter' to be complete.
void operator()(node* ptr); // forward-reference to avoid needing
}; // 'delete ptr' before the node is complete.
struct node
{
std::unique_ptr<node, node_deleter> next;
};
void node_deleter::operator()(node* ptr)
{
delete ptr;
}
Mind you, I have not tested it in MSVC, and probably you should try to upgrade to VC 11, or file a bug to Microsoft if even VC 11 cannot compile your original code.
Upvotes: 5
Reputation: 7010
If you use shared_ptr
instead of unique_ptr
, then this compiles (on VS2010). I'm guessing that the way it's implemented allows partial classes (forward declaration, etc) in the case of shared_ptr
, but not for unique_ptr
. The doc for boost::shared_ptr
definitely says it allows this, but I don't know for VS2010 if it's "said" why they're doing this behavior for one and not the other.
I'd say test it and see if it meets your needs with shared_ptr
. It's not what you want, but if it works, and the speed difference isn't a lot, then it could be OK.
Upvotes: 0
Reputation: 506847
Your code looks well-formed. In a constructor body and destructor body, a class is considered to be a complete type.
Upvotes: 3