关于SO上的unique_ptr和不完整类型的问题已经有很多,但是没有一个可以给我一个理解以下原因的概念:
// error: ... std::pair<...>::second has incomplete type
template<typename K, typename T> struct Impl {
typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type;
std::unique_ptr<iter_type> ptr;
Impl() : ptr(new iter_type()) {}
};
int main() { Impl<int,int>(); return 0; }
而以下是:
template<typename K, typename T> struct Impl {
struct Wrapper {
typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type;
iter_type iter;
};
std::unique_ptr<Wrapper> ptr;
Impl() : ptr(new Wrapper()) {}
};
int main() { Impl<int,int>(); return 0; }
我看不出技术上的区别在哪里:如果
std::pair<...>::second
(即Impl<K,T>
)在第一个示例中不完整到Impl
,则在第二个示例中也应该不完整Wrapper
。还,当足以将
unique_ptr
包装在结构中时,为什么对第一种情况有限制?UPDATE :
在DietmarKühl回答之后,我认为这个问题可以归结为以下几点:
template<typename K, typename T> struct Impl {
typename std::unordered_map<K,Impl<K,T>>::iterator ptr;
};
与
template<typename K, typename T> struct Impl {
struct Wrapper {
typename std::unordered_map<K,Impl<K,T>>::iterator iter;
};
Wrapper *ptr;
};
最佳答案
第一种情况是std::unordered_map<K, Impl<K, T>
使用不完整类型的问题:为了确定iterator
是什么,需要在仅声明std::unordered_map<K, Impl<K, T>
时实例化Impl
的某些部分。 std::unique_ptr<...>
与错误无关。您可以删除对iter_type
的使用,因为typedef
需要验证它是否为类型。
另一方面,将迭代器类型的用法包装到Wrapper
中时,在构造函数实现之前不使用此嵌套类型。当然,内联定义的函数的行为就好像该类只是完全定义的,并且它们是在类定义之外实现的,即,上面的代码等效于
template<typename K, typename T> struct Impl {
struct Wrapper {
typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type;
iter_type iter;
};
std::unique_ptr<Wrapper> ptr;
Impl();
};
template<typename K, typename T>
Impl<K, T>::Impl() : ptr(new Impl<K, T>::Wrapper()) {}
即,当需要并实例化
Wrapper
的定义时,就定义了Impl
。关于C++ 11 : unique_ptr complains about incomplete type,,但是当我包装它时不,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18424025/