2012-03-25 117 views
11

我有这样一个递归类型:模板递归类型

template<typename T> 
struct SomeType { 
    std::map<T, SomeType<T>> mapping; 
}; 

SomeType<int> foo; 

这工作正常,但更换std::mapstd::unordered_map导致编译错误,由于不完全类型。我(或gcc)在某处发生错误吗?或者这只是标准的一部分?

我还想通过模板参数(例如std::stackstd::queue)确定内部容器,但是我找不到一种方法来完成它,因为这需要定义SomeType。

不完整的例子:

template<typename T, typename C = std::map<T, SomeType<[???]>>> 
struct SomeType { 
    C mapping; 
}; 

SomeType<int, [???]> foo; 

我知道这可以运行间接来完成,但是这不是我要找的。

+1

标准库容器模板需要实例化他们完整的类型;一切都是未定义的行为。你必须忍受这一点。不过,您可以使用pimpl解决方案来解决这个问题。 – 2012-03-25 13:45:44

+0

@KerrekSB是这样吗?该死,我经常编写n-ary树,其节点是用'std :: vector children'来实现的。 – 2012-03-25 13:46:42

+0

@KonradRudolph:好的,你必须确保在实例化时类型已经完成。这可能是一个微妙的问题。 – 2012-03-25 13:57:51

回答

7

您的课程在其定义的最终}之前的任何地方都不完整。因此mapping成员在其类型的模板参数中使用不完整类型SomeType

The standard does not allow this, and it is pure luck that it works with some STL containers.

你的第二个问题属于相同的答案下 - 它是非法的这样做摆在首位。

+0

嗯。不幸的是,我不理解这篇文章中关于为什么'std :: map '不完整的类型原则上不能工作的论点。这不是很像'std :: vector >',哪个*可以*原则上工作('std :: pair '不完整)?其他容器也一样。 – 2012-03-25 16:23:22

+0

如果这需要解释,我建议打开一个聊天室,这并不难,只是不适合评论部分...现在,我该如何明确地打开一个聊天室关于这... – Irfy 2012-03-25 16:31:11

+1

让我们在这里聊天:http:///chat.stackoverflow.com/rooms/9282/stl-with-incomplete-types – Irfy 2012-03-25 16:34:00

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) { } 
}; 
+1

boost :: container库为大多数STL类型提供了替代方案,这些类型允许不完整类型的递归容器。它目前不提供unmarked_map – mark 2012-03-26 07:47:02

+0

@mark:谢谢,这很好理解! – 2012-03-26 08:03:55

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

是否有可能更改第一行,使Container的默认值为std :: vector? – 2015-01-25 11:36:44

+0

@NielsLohmann,从技术上讲,你可以编写'template class Container = std :: vector>',但它会与'std :: unordered_map'不一致。因为地图是_assosiative_ conrtainer,矢量只是一个数组。 – Lol4t0 2015-01-25 20:15:58