我正在使用递归继承的递归模板类 我试图定义一个获得第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));
}
...
有更直接或“正确”的方法吗?
答案 0 :(得分:2)
我的挖掘工作看起来有些仓促。
显然使用模板的完全限定名称(在我的示例中为::record
):
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));
}
答案 1 :(得分:1)
没有必要使用任何技巧让编译器意识到您使用record
作为模板名称而不是引用当前实例化的类型名称。见[temp.local] / 1,强调我的:
与普通(非模板)类一样,类模板具有 inject-class-name (第9条)。 inject-class-name 可用作模板名称或类型名称。当它与 template-argument-list 一起使用时, 作为模板 template-parameter 的模板参数,或 elaborated-type-specifier中的最终标识符朋友类模板声明的em>,它指的是类模板本身。否则,它等同于 template-name ,后跟
<>
中包含的类模板的 template-parameters 。
您发布的解决方法是正确的,但不应该需要;这是编译器中的一个错误。