gpt4 book ai didi

c++ - 递归模板类型声明

转载 作者:行者123 更新时间:2023-12-02 10:11:48 25 4
gpt4 key购买 nike

我正在尝试创建一个包含N个嵌套模板类型的结构:
我要做的代码是:


// slab (base case essentially)
template<typename T, uint32_t nvecs = 8, align_policy ap = align_policy::none>
struct slab {
T t;
};

// wrapper for either slab or other super_slabs
template<typename T,
uint32_t nvecs = 8,
uint32_t inner_nvec = 8,
typename inner_slab_t = slab<T, inner_nvec>>
struct super_slab {
inner_slab_t ist;
};

// hopefully correct functions to extract Nth values for argument pack
template<typename... Vals>
constexpr uint32_t
_get_0(uint32_t v, Vals... vals) {
return v;
}

template<typename... Vals>
constexpr uint32_t
_get_N(int32_t n, uint32_t v, Vals... vals) {
return n <= 0 ? _get_0(vals...) : _get_N(n - 1, vals...);
}

template<typename... Vals>
constexpr uint32_t
get_N(int32_t n, Vals... vals) {
return _get_N(n, vals...);
}


// first approach I tried
#ifdef APPROACH_A
template<typename T, uint32_t nlevels, uint32_t level, uint32_t... other_nvecs>
struct type_helper {
using type = typename std::conditional<
level <= 1,
slab<T, other_nvecs...>,
super_slab<T,
get_N(nlevels - level, other_nvecs...),
get_N(nlevels - (level + 1), other_nvecs...),
typename type_helper<T, nlevels, level - 1, other_nvecs...>::
type>>::type;
};
#endif

// second approach I tried
#ifdef APPROACH_B
template<typename T, uint32_t nlevels, uint32_t level, uint32_t... other_nvecs>
struct type_helper;
template<typename T, uint32_t nlevels, uint32_t level, uint32_t... other_nvecs>
struct type_helper {
using type = super_slab<
T,
get_N(nlevels - level, other_nvecs...),
get_N(nlevels - (level + 1), other_nvecs...),
typename type_helper<T, nlevels, level - 1, other_nvecs...>::type>;
};

template<typename T, uint32_t nlevels, uint32_t level, uint32_t other_nvecs>
struct type_helper {
using type = slab<T, nvecs>;
};
#endif

// struct I want to use for API.
template<typename T, uint32_t levels, uint32_t... level_nvecs>
struct slab_manager {
using slab_t =
typename type_helper<T, levels, levels, level_nvecs...>::type;
};
APPROACH_A会编译,但是当我尝试使用以下方法实例化它时:
slab_manager<uint64_t, 1, 8> m;
我得到错误:
slab_manager.h: In instantiation of ‘struct type_helper<long unsigned int, 1, 4294966399, 8>’:
slab_manager.h:39:36: recursively required from ‘struct type_helper<long unsigned int, 1, 0, 8>’
slab_manager.h:39:36: required from ‘struct type_helper<long unsigned int, 1, 1, 8>’
slab_manager.h:63:70: required from ‘struct slab_manager<long unsigned int, 1, 8>’
obj_slab_test.cc:213:34: required from here
slab_manager.h:36:25: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
get_N(nlevels - level, other_nvecs...),
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
我真的看不到 ‘struct type_helper<long unsigned int, 1, 4294966399, 8>’:会如何通过,因为传递 1是初始级别应该导致它刚达到 std::conditional中的基本情况。我的猜测是问题是 std::conditional完全展开了这两种选择
但是当我尝试方法B时,出现以下错误:
slab_manager.h:43:68: error: template parameter ‘unsigned int ...other_nvecs’
template<typename T, uint32_t nlevels, uint32_t level, uint32_t... other_nvecs>
^~~~~~~~~~~
slab_manager.h:55:8: error: redeclared here as ‘unsigned int other_nvecs’
struct type_helper {
^~~~~~~~~~~
slab_manager.h: In instantiation of ‘struct type_helper<long unsigned int, 1, 4294966399, 8>’:
slab_manager.h:51:75: recursively required from ‘struct type_helper<long unsigned int, 1, 0, 8>’
slab_manager.h:51:75: required from ‘struct type_helper<long unsigned int, 1, 1, 8>’
slab_manager.h:63:70: required from ‘struct slab_manager<long unsigned int, 1, 8>’
obj_slab_test.cc:213:34: required from here
slab_manager.h:49:14: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
get_N(nlevels - level, other_nvecs...),
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这表明A失败的原因不是 std::conditional引起的,而是使我更加困惑,因为到目前为止,我在每本指南中都看到了用基本情况重新声明类型的方法。
我的猜测是调用 slab_manager<uint64_t, 1, 8> m;将设置 slab_t = slab<uint64_t, 8>例如 slab_manager<uint64_t, 3, 2, 4, 8> m;将设置 slab_t = super_slab<uint64_t, 2, 4, super_slab<uint64_t, 4, 8, slab<uint64_t, 8>。任何帮助,将不胜感激。谢谢!
编辑后代:
这个问题很多。正如@cdhowie指出的那样,我没有正确遵循指南。
这是一个可行的解决方案:
template<typename... Vals>
constexpr int32_t
_get_0(int32_t v, Vals... vals) {
return v;
}


template<typename... Vals>
constexpr int32_t
_get_0(int32_t v) {
return v;
}

template<typename... Vals>
constexpr int32_t
_get_N(int32_t n, Vals... vals) {
return n <= 0 ? _get_0(vals...) : _get_N(n - 1, vals...);
}


template<typename... Vals>
constexpr int32_t
get_N(int32_t n, Vals... vals) {
return _get_N(n, vals...);
}


template<typename T, int32_t nlevels, int32_t level, int32_t... other_nvecs>
struct type_helper;


template<typename T, int32_t nlevel, int32_t... other_nvecs>
struct type_helper<T, nlevel, 0, other_nvecs...> {
typedef slab<T, get_N(nlevel, other_nvecs...)> type;
};

template<typename T, int32_t nlevels, int32_t level, int32_t... other_nvecs>
struct type_helper {
typedef super_slab<T,
get_N(nlevels - level, other_nvecs...),
get_N(nlevels - (level + 1), other_nvecs...),
typename type_helper<T, nlevels, level - 1, other_nvecs...>::type>
type;
};


template<typename T, int32_t levels, int32_t... level_nvecs>
struct slab_manager {
using slab_t = typename type_helper<T, levels, levels - 1, level_nvecs...>::type;
};

最佳答案

在方法A中,由于std::conditional的两个“分支”中的两种类型仍然被实例化,即使条件选择了另一种类型,您仍具有编译时整数下溢。结果,您的type_helper导致尝试实例化的无限递归。
方法B的编译错误是您的特化语法错误​​。这个:

template<typename T, uint32_t nlevels, uint32_t level, uint32_t other_nvecs>
struct type_helper {
using type = slab<T, nvecs>;
};
应该是这样的:
template<typename T, uint32_t nlevels, uint32_t level, uint32_t other_nvecs>
struct type_helper<T, nlevels, level, other_nvecs> {
using type = slab<T, nvecs>;
};
方法B陷入与方法A完全相同的无限递归问题: type_helper<T, nlevels, level, other_nvecs...>将始终实例化 type_helper<T, nlevels, level - 1, other_nvecs...>level下溢,递归一直持续到编译器放弃为止。
在这种情况下,终止递归的方式是在 level为零时定义一个特殊情况:
template<typename T, uint32_t nlevels, uint32_t... other_nvecs>
struct type_helper<T, nlevels, 0, other_nvecs...> {
using type = // whatever makes sense in your case
};
我不知道 type应该在这里(但我想你应该这样做)。
您还可能遇到最终终止情况,其中 level为零,而 other_nvecs为空:
template<typename T, uint32_t nlevels>
struct type_helper<T, nlevels, 0> {
using type = // something
};

关于c++ - 递归模板类型声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63239178/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com