关于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/

10-11 00:02