递归/自引用模板(使用指针)是否可以在C++中实例化和/或专门化



我想使用映射、向量和数组从STL实例化一个模板,如下所示:

映射<some_type,向量<映射<some_type,矢量>>gt;要素;

省略号只是表示无限递归定义的伪代码,当然这是不可能键入的。基本上,向量应该只包含指向其他映射的指针,这些映射在结构/定义上与包含向量的映射相同。我知道有使用类和结构的变通方法,问题是是否可以只使用模板。我希望我能以某种方式将整个外部地图定义为某种";模板变量";或其他位置保持器,例如";T";,然后写下以下内容:

映射<some_type,向量<T*>gt;要素;

其中我将单独定义T为指代整个映射。但由于递归,这样的变量T将根据其本身来定义,即本身就是T的子组件。后来,我会在运行时根据需要在堆上分配更多的映射,并在向量中插入指向它们的指针,这样我就可以递归地(经常(遍历到向量中的映射,这样我就能在堆上实例化更多的映射,再次在向量中保持指向它们的指针。

有没有(优雅的(方法可以做到这一点(如果有的话(?

通过提取递归变量,您走上了正确的轨道

template <typename Self>
using F = std::map<int, std::vector<Self*>>;

问题是找到一个类型CCD_ 1,使得CCD_。这就是所谓的寻找不动点。在这些术语中,我们希望模板Fix采用模板模板参数,使得Fix<F> == F<Fix<F>>

抽象地说,在懒惰函数语言中,Fix<F> = F<Fix<F>>可以作为Fix<F>的定义。巧合的是,这告诉了我们C++中到底发生了什么故障。在C++表示法中,这个假设的定义看起来像:

template <template<typename> typename F>
using Fix = F<Fix<F>>; // does not compile

这从根本上取决于懒惰,但模板本质上是懒惰的,所以这不是问题。真正的问题是名字查找。我们不能在C++中引用右侧的Fix。这是一种人为的限制,但这就是我们的语言。

我看不到解决这个问题的方法,所以我无法避免引入一个通用的帮助结构:

template <template<typename> typename F>
struct Fix : F<Fix<F>> { };

尽管别名不能在定义中引用自己的名称,但类和结构可以。

所有这些都解决了,我们有了解决方案:

// Our type
using Type = Fix<F>;
// It instantiates
auto map = Type{};
// The inner type is the same as the outer type
using inner_type = std::decay_t<decltype(*std::declval<Type::mapped_type::value_type>())>;
static_assert(std::is_same_v<Type, inner_type>);
// We can push_back the address of ourself
map[0].push_back(&map);

请参见godbolt。

最新更新