首页 文章

如何将当前类模板用作另一个模板的模板参数?

提问于
浏览
0

我正在使用递归继承的递归模板类 .
我'm trying to define an abstract way of getting the n-th base (like base 0 is the current class, base 1 is its base, base 2 is the base'的基地等) .

(在此示例中,模板参数为 size_t ,但同样的原则适用于 typenameclass . )

我可以使用一个部分专门的辅助结构来做到这一点 . 但我想让它独立于模板(并且每当我有一个递归模板时都不会创建一个辅助结构),如下所示:

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 是最终的类而不是模板 . 我想使用"current template"而不是"currently instantiated class"之类的东西 .

我发现的唯一解决方法(在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));
}
...

是否有更直接或“正确”的方法来做到这一点?

2 回答

  • 2

    没有必要使用任何技巧让编译器意识到您使用 record 作为模板名称而不是引用当前实例化的类型名称 . 见[temp.local] / 1,强调我的:

    与普通(非模板)类一样,类模板具有注入类名(第9条) . inject-class-name可以用作模板名称或类型名称 . 当它与template-argument-list一起使用时,作为模板模板参数的模板参数,或作为友元类模板声明的详细类型说明符中的最终标识符,它引用类模板本身 . 否则,它等同于template-name,后跟<>中包含的类模板的template-parameters .

    您发布的解决方法是正确的,但不应该需要;这是编译器中的一个错误 .

  • 1

    看起来我挖掘时有点仓促 .

    显然使用模板's fully qualified name works (in my example it' s ::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));
        }
    

相关问题