模板化的递归数据类型

templated recursive data types

本文关键字:递归 数据类型      更新时间:2023-10-16

我有一个递归数据类型,如下所示:

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

这很好,但是用std::unordered_map替换std::map会由于类型不完整而导致编译错误。我(或gcc)在哪里出错了吗?还是这只是标准的一部分?

我也想让内部容器由模板参数(如std::stackstd::queue)确定,但我无法找到实现这一点的方法,因为这需要已经定义SomeType。

不完整的示例:

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

我知道这可以通过运行时间接实现,但这不是我想要的。

您的类在其定义的最终}之前的任何位置都是不完整的。因此,mapping成员在其类型的模板参数中使用了不完整的类型SomeType

该标准不允许这样做,而且它与一些STL容器一起工作纯属运气。

你的第二个问题属于相同的答案——首先这样做是违法的。

由于明显的原因,不能用递归默认参数定义模板。您也不能在不完整的类型上实例化标准库容器模板,因为标准是这么说的(否则就是未定义的行为)。不过,通常的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) { }
};

虽然不能对容器使用不完全类型,但可以使用智能指针。虽然你不能用未定义的类型参数创建模板类型,但你可以在这里使用一些技巧:

template<typename T, template <typename U, typename V, typename... Args> class Container = std::unordered_map >
struct SomeType {
    Container<T, std::unique_ptr<SomeType> > mapping;
};