我有一个这样的递归数据类型:
template<typename T>
struct SomeType {
std::map<T, SomeType<T>> mapping;
};
SomeType<int> foo;
这样可以正常工作,但将std::map
替换为std::unordered_map
会因类型不完整而导致编译错误。我(或gcc)在某个地方犯了错误吗?或者这只是标准的一部分?
我还希望内部容器由模板参数(例如std::stack
和std::queue
)确定,但我无法找到一种方法来实现它,因为这需要SomeType来已定义。
不完整的例子:
template<typename T, typename C = std::map<T, SomeType<[???]>>>
struct SomeType {
C mapping;
};
SomeType<int, [???]> foo;
我知道这可以通过运行时间接完成,但这不是我想要的。
答案 0 :(得分:7)
您的课程在其定义的最终}
之前的任何地方都是不完整的。因此mapping
成员在其类型的模板参数中使用了不完整的类型SomeType
。
The standard does not allow this, and it is pure luck that it works with some STL containers.
你的第二个问题属于同样的答案 - 首先这样做是违法的。
答案 1 :(得分:4)
出于显而易见的原因,您无法使用递归默认参数定义模板。您也无法在不完整类型上实例化标准库容器模板,因为标准是这样说的(否则它是未定义的行为)。但是,通常的PIMPL习惯可能会有所帮助:
#include <map>
#include <memory>
template <typename T> class SomeType
{
typedef std::map<T, SomeType<T>> map_type;
typedef std::unique_ptr<map_type> map_ptr;
map_ptr pimpl;
public:
SomeType() : pimpl(new map_type) { }
};
答案 2 :(得分:3)
虽然您不能将不完整类型与容器一起使用,但您可以使用智能指针来执行此操作。 虽然您无法使用未定义的类型参数创建模板类型,但您可以在此处使用一些技巧:
template<typename T, template <typename U, typename V, typename... Args> class Container = std::unordered_map >
struct SomeType {
Container<T, std::unique_ptr<SomeType> > mapping;
};