在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
1}}也在第二个。也,
当将unique_ptr
包装在结构中时,为什么第一种情况有限制?
更新:
在DietmarKühl回答之后,我认为问题可以归结为以下几点:
template<typename K, typename T> struct Impl {
typename std::unordered_map<K,Impl<K,T>>::iterator ptr;
};
VS
template<typename K, typename T> struct Impl {
struct Wrapper {
typename std::unordered_map<K,Impl<K,T>>::iterator iter;
};
Wrapper *ptr;
};
答案 0 :(得分:3)
第一种情况下的问题是不完整类型与std::unordered_map<K, Impl<K, T>
一起使用:要确定iterator
是什么,std::unordered_map<K, Impl<K, T>
的部分需要在{{1}时实例化只是声明了。 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
被定义。