2012-05-02 4 views
4

неполного типа У меня естьстанд :: unique_ptr <T> ошибки

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

Я получаю ошибку компиляции на отмеченной линии в VS10. Должен ли я иметь возможность использовать неполный тип в этом случае (создать экземпляр шаблона - конструктор - здесь для int в качестве примера)? Есть ли работа?

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>   ] 
+0

Выполняет ли форвардное объявление ошибку компиляции? –

+3

http://stackoverflow.com/questions/9954518/stdunique-ptr-with-an-incomplete-type-wont-compile – CppLearner

+0

@CppLearner видел это тоже. Написал деструктор для node(), но не использовал – Ghita

ответ

4

Требование полного типа в точке создания шаблона связано с std::default_delete, поэтому, возможно, вы можете обходить его, предоставив пользовательский делектор.

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; 
} 

Имейте в виду, я не проверял его в MSVC, и, возможно, вы должны попытаться перейти на VC 11 или file a bug to Microsoft если даже VC 11 не может компилировать исходный код.

+0

Это работает. Tnx. – Ghita

3

Ваш код выглядит хорошо сформирован. В теле конструктора и тело деструктора класс считается полным типом.

+0

компиляция с gcc 4.5.1 (C++ 0x) в порядке ... действительно интересно, есть ли работа вокруг VS10 теперь – Ghita

+0

компиляция с gcc 4.3.4, хотя (с использованием http: // ideone. com) У меня та же проблема, что и у VS10 – Ghita

+1

@Ghita: GCC Ideone GCC 4.3.x не включает поддержку C++ 11, поэтому у нее нет 'std :: unique_ptr <>', что довольно-таки проблема _different_ чем с VC++ 2010. – ildjarn

0

Если вы используете shared_ptr вместо unique_ptr, то компиляция (на VS2010). Я предполагаю, что способ, которым он реализован, допускает частичные классы (форвардная декларация и т. Д.) В случае shared_ptr, но не для unique_ptr. Документ для boost::shared_ptr определенно говорит, что он позволяет это, но я не знаю, VS2010, если он «сказал», почему они делают это поведение для одного, а не для другого.

Я бы сказал, протестируйте его и посмотрите, соответствует ли он вашим потребностям shared_ptr. Это не то, что вы хотите, но если это сработает, и разница в скорости не очень много, тогда это может быть ОК.

+0

Я бы предпочел не использовать shared_ptr вместо уникального указателя. – Ghita

+0

Согласен. Для того, что вы делаете, 'unique_ptr' кажется подходящим выбором, но иногда вам нужно использовать то, что работает, даже если это не то, что вы изначально хотели использовать. Я просто публиковал как «хорошо, это заставило бы ваш код работать», даже если это не объяснение, которое вы хотели. –