【发布时间】:2017-10-26 21:05:07
【问题描述】:
我正在使用递归继承的递归模板类。
我正在尝试定义一种获取第 n 个基数的抽象方法(例如基数 0 是当前类,基数 1 是它的基数,基数 2 是基数的基数等)。
(在本例中,模板参数为size_t,但同样的原则也适用于typename 或class。)
我可以使用部分专用的辅助结构来做到这一点。但我想让它独立于模板(并且在我有递归模板时不制作辅助结构),如下所示:
namespace helper
{
template<template<size_t...> typename templ, size_t pos, size_t s0, size_t... rest>
struct getter
{
typedef typename getter<templ, pos - 1, rest...>::type type;
type &operator()(templ<s0, rest...> &s)
{
getter<templ, pos - 1, rest...> getter;
return getter(static_cast<templ<rest...>&> (s));
}
};
template<template<size_t...> typename templ, size_t s0, size_t... rest>
struct getter<templ, 0, s0, rest...>
{
typedef templ<s0, rest...> type;
type &operator()(templ<s0, rest...> &s)
{
return s;
}
};
}
现在,在我的模板类中,我想使用这个助手来创建一个函数 get<size_t n>(),它返回一个对第 n 个基数的引用(代码在 get 声明处编译失败):
template<size_t...>
struct record {};
template<size_t n, size_t... rest>
struct record<n, rest...> : record<rest...>, value<n>
{
template<size_t pos>
typename helper::getter<record, pos, n, rest...>::type::value_type &get()
{
helper::getter<record, pos, n, rest...> getter;
return static_cast<typename helper::getter<record, pos, n, rest...>::type::value_type&>(getter(*this));
}
};
这失败了,因为在record 模板中,record 是最终类而不是模板。我想使用“当前模板”之类的东西,而不是“当前实例化的类”。
我发现的唯一解决方法(在 Visual Studio 2015 下有效)是使用全局别名来复制模板:
template<size_t...s>
using g_record = record<s...>;
然后修改get声明调用全局别名(指向同一类型):
...
template<size_t pos>
typename helper::getter<g_record, pos, n, rest...>::type::value_type &get()
{
helper::getter<g_record, pos, n, rest...> getter;
return static_cast<typename helper::getter<g_record, pos, n, rest...>::type::value_type&>(getter(*this));
}
...
有没有更直接或更“正确”的方法来做到这一点?
【问题讨论】:
标签: c++ templates recursion metaprogramming