C++ C++;模板类继承

C++ C++;模板类继承,c++,class,templates,inheritance,name-lookup,C++,Class,Templates,Inheritance,Name Lookup,如何定义从模板类继承的模板类 我想将std::queue和std::priority\u queue包装为基类。在我的例子中是LooperQueue。 我使用StdQueue的方式是autoqueue=newstdqueue() 我的类定义编译器 错误日志: In file included from /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/Painter.cpp:10: /Users/rqg/ASProjects/PboTest

如何定义从模板类继承的模板类

我想将
std::queue
std::priority\u queue
包装为基类。在我的例子中是
LooperQueue
。 我使用
StdQueue
的方式是
autoqueue=newstdqueue()

我的类定义编译器

错误日志:

  In file included from /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/Painter.cpp:10:
  /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/util/StdQueue.h:14:5: error: unknown type name 'size_type'; did you mean 'size_t'?
      size_type size() override;
      ^~~~~~~~~
      size_t
  /Users/rqg/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/5.0.300080/include/stddef.h:62:23: note: 'size_t' declared here
  typedef __SIZE_TYPE__ size_t;
                        ^
  In file included from /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/Painter.cpp:10:
  /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/util/StdQueue.h:16:5: error: unknown type name 'reference'
      reference front() override;
      ^
  /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/util/StdQueue.h:20:21: error: unknown type name 'value_type'; did you mean 'ARect::value_type'?
      void push(const value_type &x) override;
                      ^~~~~~~~~~
                      ARect::value_type
  /Users/rqg/Library/Android/sdk/ndk-bundle/sysroot/usr/include/android/rect.h:44:21: note: 'ARect::value_type' declared here
      typedef int32_t value_type;
代码:

  In file included from /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/Painter.cpp:10:
  /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/util/StdQueue.h:14:5: error: unknown type name 'size_type'; did you mean 'size_t'?
      size_type size() override;
      ^~~~~~~~~
      size_t
  /Users/rqg/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/5.0.300080/include/stddef.h:62:23: note: 'size_t' declared here
  typedef __SIZE_TYPE__ size_t;
                        ^
  In file included from /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/Painter.cpp:10:
  /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/util/StdQueue.h:16:5: error: unknown type name 'reference'
      reference front() override;
      ^
  /Users/rqg/ASProjects/PboTest/muses/src/main/cpp/util/StdQueue.h:20:21: error: unknown type name 'value_type'; did you mean 'ARect::value_type'?
      void push(const value_type &x) override;
                      ^~~~~~~~~~
                      ARect::value_type
  /Users/rqg/Library/Android/sdk/ndk-bundle/sysroot/usr/include/android/rect.h:44:21: note: 'ARect::value_type' declared here
      typedef int32_t value_type;
\ifndef PBOTEST\u LOOPERQUEUE\u H
#定义PBOTEST_LOOPERQUEUE_H
#包括
#包括
模板
类循环队列{
公众:
typedef typename序列::值\类型值\类型;
typedef typename序列::引用引用;
typedef typename序列::const_reference const_reference;
typedef typename序列::大小\类型大小\类型;
类型定义序列容器\ U类型;
虚拟大小\类型大小()=0;
虚拟参考前沿()=0;
虚拟void pop()=0;
虚拟无效推送(常量值_type&x)=0;
};
#endif//PBOTEST\u LOOPERQUEUE\u H
#如果NDEF PBO测试(标准队列)
#定义PBOTEST_STDQUEUE_H
#包括“LooperQueue.h”
模板
类StdQueue:公共循环队列{
公众:
大小\类型大小()覆盖;
参考前端()覆盖;
void pop()覆盖;
无效推送(常量值类型和x)覆盖;
公众:
私人:
std::队列mQueue;
};
#endif//PBOTEST\u STDQUEUE\H

< /代码> 我将使用一个更简单的例子来给你同样的错误,考虑一个只有一个别名的基类和一个试图使用它的子类:

template <typename T>
class Base {
 public:
  using value_type = T;
};

template <typename T>
class Derived : public Base<T> {
  value_type func();  // error
};
或者使用
声明告诉编译器您打算使用基类类型别名

template <typename T>
class Derived : public Base<T> {
  using typename Base<T>::value_type;
  value_type func();
};
然后,
Derived
必须在其范围内的其他地方查找
value\u type
,这就是它在原始代码中所做的。它尝试查找
值\u type
,但失败。这种行为会导致一些令人惊讶的结果:

using value_type = char;
template <typename T>
class Derived : public Base<T> {
  value_type func(); // this is the global value_type = char, always
};
使用value\u type=char;
模板
派生类:公共基{
value_type func();//这是全局值_type=char,始终为
};

有关相关主题的详细说明

大多数(如果不是全部的话)编译错误都是由于在派生类的名称查找过程中未检查基类中的类型造成的。C++标准表示您应该完全限定类型名称(见)。换句话说,模板基类中的类型在派生类中是不可见的,除非它们是完全限定的。下面是一个使用
g++-6.3.0-std=c++14编译和运行的简单示例:

#include <iostream>
#include <deque>

using namespace std;

template <typename T, typename S = deque<T> >
class Base
{
public:
    typedef typename S::size_type size_type;

    virtual size_type size() = 0;
};


template <typename T, typename S = deque<T> >
class MyClass : public Base<T, S>
{
public:
    // type name has to be fully qualified
    typedef typename Base<T,S>::size_type size_type;

    // you could use "typename Base<T,S>::size_type" here instead
    size_type size() override { return 0; }
};


int main()
{
    MyClass<int> c;
    cout << c.size() << endl;
}
#包括
#包括
使用名称空间std;
模板
阶级基础
{
公众:
typedef typename S::size\u type size\u type;
虚拟大小\类型大小()=0;
};
模板
类MyClass:公共基
{
公众:
//类型名称必须是完全限定的
typedef typename Base::size\u type size\u type;
//您可以在这里使用“typename Base::size\u type”
size_type size()重写{return 0;}
};
int main()
{
MyClass c;

CUT< P>这里的问题是基类<代码> LoopQueWu/C++ >是依赖的基类,它依赖于模板参数<代码> TP 和<代码>序列,然后在不知道模板参数的情况下无法确定其完整类型。(如
size\u-type
reference
value\u-type
)不会在依赖基类中查找

要更正代码,只需使用基类名称限定名称就足够了;然后,只能在实例化时查找这些名称,届时将知道必须探究的确切基类专门化

template<typename _Tp, typename _Sequence = std::deque<_Tp> >
class StdQueue : public LooperQueue<_Tp, _Sequence> {
public:
    typename LooperQueue<_Tp, _Sequence>::::size_type size() override;
    typename LooperQueue<_Tp, _Sequence>::reference front() override;
    void pop() override;
    void push(const typename LooperQueue<_Tp, _Sequence>::value_type &__x) override;
private:
    std::queue<_Tp, _Sequence> mQueue;
};
模板
类StdQueue:公共循环队列{
公众:
typename LooperQueue:::size_type size()覆盖;
typename LooperQueue::reference front()覆盖;
void pop()覆盖;
void push(const typename LooperQueue::value\u type&\u x)覆盖;
私人:
std::队列mQueue;
};

在没有文件名和行号的情况下发布编译器错误很糟糕。此外,我建议使用“using”而不是typedef。语法更清晰,我认为它有时也能提供更好的错误消息。此外,不允许使用以下划线开头,后跟大写字母的名称,或任何以两个下划线开头的名称核心。例如,不允许使用u序列。@xaxxon任何带有两个连续下划线的标识符都是不允许的allowed@xaxxon很抱歉我的错误日志帖子。我删除了下划线,但错误保持不变。我不理解“
使用
而不是typedef”。是否有更多详细信息
typedef typename Base::size\u type size\u type;
可以通过
使用typename Base::size\u type;
完成?是的,所有
typedef
都可以通过
使用
完成(别名声明),我更喜欢使用别名声明而不是
typedef
。但是,我决定离开
typedef
s,使示例更接近Fantasy_RQG的原始代码。您的代码工作得很好,但我无法将函数定义拆分为声明和定义。有什么方法可以做到这一点吗?将函数声明从定义,首先将定义留在类中。它将如下所示:
size\u type size()覆盖;
然后,在类之后或
.C
文件中:
模板类型名称MyClass::size\u type MyClass::size(){return 0;}
当然,您可以在不同的行上编写定义。如果您想让我编辑答案中的代码以反映这一点,请让我知道。顺便说一句,如果您将模板定义放置在
.C
.cpp
文件中,您需要显式地为特定类型实例化模板类,这是一种限制(和另一个主题)。我通常只将定义放在
.h
文件中。我可以定义吗
template<typename _Tp, typename _Sequence = std::deque<_Tp> >
class StdQueue : public LooperQueue<_Tp, _Sequence> {
public:
    typename LooperQueue<_Tp, _Sequence>::::size_type size() override;
    typename LooperQueue<_Tp, _Sequence>::reference front() override;
    void pop() override;
    void push(const typename LooperQueue<_Tp, _Sequence>::value_type &__x) override;
private:
    std::queue<_Tp, _Sequence> mQueue;
};