C ++找不到从当前模板类继承的模板基类中定义的类型 [英] C++ cannot find type defined in template base class which inherits from the current template class

查看:153
本文介绍了C ++找不到从当前模板类继承的模板基类中定义的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写模板的变体定义super类型习语的类.类Inherit引入了类型Super来表示可能非常长的超级类型,并且还需要知道派生的类型New来做一些我在这里没有显示的额外操作.

I'm trying to write a variation of the template class defining a super type idiom. The class Inherit introduces the type Super to denote the possibly very long super type, and also needs to know the derived type New to do some extra things which I'm not showing here.

如果传递给New的类型不是模板,但对于模板失败,则可以正常工作.这是用clang++-3.8 -std=c++1y -Wall编译的完整示例(gcc给出相同的输出):

This works fine if the type passed to New is not a template, but fails with templates. Here is a full example compiled with clang++-3.8 -std=c++1y -Wall (gcc gives the same output):

struct SomeBase {};

template<class New, class Base>
struct Inherit : Base {
    using Super = Inherit<New, Base>;
};

struct NonTemplate : Inherit<NonTemplate, SomeBase> {
    using X = Super;
    // compiles and is nice and short
};

template<class T>
struct Template : Inherit<Template<T>, SomeBase>
{
    using A = Super;
    // error: unknown type name 'Super'; did you mean 'NonTemplate::Super'?

    using B = typename Super;
    // error: expected a qualified name after 'typename'

    using C = Inherit::Super;
    // error: 'Inherit' is not a class, namespace, or enumeration

    using D = typename Inherit<Template<T>, SomeBase>::Super;
    // compiles, but what's the point?
};

int main() {
    return 0;
}

如果不需要New参数,我也可以将Inherit与模板一起使用,但是我确实需要New.我可以使用选项D来编译代码,但这会破坏整个目的.

If I didn't need the New parameter I am also able to use Inherit with templates, but I really need New. I could make the code compile by using option D but that defeats the whole purpose.

我有两个问题:

  1. 阻止类型名称Super的语言问题到底是什么? 从在类Template中被了解,为什么在NonTemplate情况下有什么不同?
  2. 有人对这个问题有一个好的解决方案的想法吗?
  1. What exactly is the language issue which prevents the type name Super from being known inside the class Template and why is that different in the NonTemplate case?
  2. Does anyone have an idea for a good solution to this problem?

推荐答案

问题是Inherit<Template<T>, SomeBase>依赖的基类,即该类取决于模板参数.依赖基类中的名称对于不合格的查找是隐藏的,因此您需要对名称进行限定.

The issue is that Inherit<Template<T>, SomeBase> is a dependent base class, i.e. the class depends on a template parameter. Names in dependent base class are hidden from unqualified lookup, so you need to qualify the name.

typename是必需的,因为Inherit<Template<T>, SomeBase>::Super是从属名称,编译器需要您告诉它命名类型,因为只能在实例化时确定它.

typename is needed because Inherit<Template<T>, SomeBase>::Super is a dependent name and the compiler needs you to tell it that it names a type, as it can only be certain at instantiation time.

请参见位置和位置为什么我必须放置模板"和类型名称"关键字?以深入说明typename关键字.

See Where and why do I have to put the "template" and "typename" keywords? for an in-depth explanation of the typename keyword.

对于解决方案,您可以将Super分解为类型特征:

As for solutions, you could factor Super out into a type trait:

template<class New, class Base>
struct Inherit : Base {
};

namespace detail {
    template <class New, class Base>
    Inherit<New,Base> Super (const Inherit<New, Base>&);
}
template <class T>
using Super = decltype(detail::Super(std::declval<T>()));

这使用法更加简单:

template<class T>
struct Template : Inherit<Template<T>, SomeBase>
{
    using D = Super<Template>;
};


如果发现自己需要多个基类,可以将其概括化:


If you find yourself needing this for multiple base classes, you could generalise it:

namespace detail {
    template <template <typename...> class T, class... Args>
    T<Args...> Super (const T<Args...>&);
}
template <template <typename...> class Base, class Derived>
using Super = decltype(detail::Super<Base>(std::declval<Derived>()));

template <typename T>
using InheritSuper = Super<Inherit,T>;

template<class T>
struct Template : Inherit<Template<T>, SomeBase>
{
    using D = InheritSuper<Template>;
};

这篇关于C ++找不到从当前模板类继承的模板基类中定义的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆