C ++模板类继承

Fan*_*RQG 3 c++ inheritance templates class name-lookup

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

我想包装std::queuestd::priority_queue转到基类。就我而言LooperQueue。我用StdQueue这种方式auto queue = new StdQueue<LooperMessage *>()

我的课定义编译器抱怨

错误日志:

  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;
Run Code Online (Sandbox Code Playgroud)

码:

  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;
Run Code Online (Sandbox Code Playgroud)
#ifndef PBOTEST_LOOPERQUEUE_H
#define PBOTEST_LOOPERQUEUE_H

#include <queue>
#include <cstdlib>

template<typename Tp, typename Sequence = std::deque<Tp> >
class LooperQueue {
public:

    typedef typename Sequence::value_type                value_type;
    typedef typename Sequence::reference                 reference;
    typedef typename Sequence::const_reference           const_reference;
    typedef typename Sequence::size_type                 size_type;
    typedef          Sequence                            container_type;


    virtual size_type size()  = 0;

    virtual reference front() = 0;

    virtual void pop()= 0;

    virtual void push(const value_type &x) = 0;
};


#endif //PBOTEST_LOOPERQUEUE_H
Run Code Online (Sandbox Code Playgroud)

Rya*_*ing 5

我将使用一个更简单的示例,该示例将给您带来相同的错误,请考虑一个仅定义了一个别名的基类,并尝试使用它的子类:

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

template <typename T>
class Derived : public Base<T> {
  value_type func();  // error
};
Run Code Online (Sandbox Code Playgroud)

由于模板的疯狂性质,编译器目前无法知道到底value_type是什么。您必须通过限定它来告诉它它来自基类:

template <typename T>
class Derived : public Base<T> {
  typename Base<T>::value_type func();
};
Run Code Online (Sandbox Code Playgroud)

或告诉编译器using您打算使用基类类型别名的声明

template <typename T>
class Derived : public Base<T> {
  using typename Base<T>::value_type;
  value_type func();
};
Run Code Online (Sandbox Code Playgroud)

编译器在知道什么并实例化模板之前实际上无法知道其中Base<T>包含。为什么不能只看基本模板?-从理论上讲这样的事情是可能的,但它不知道将提供哪些专业。如果你有其他地方value_typeT

template<>
class Base<int> {};
Run Code Online (Sandbox Code Playgroud)

然后Derived<int>必须value_type在其范围内寻找其他地方,这就是您原始代码中要做的。它尝试查找value_type失败。此行为可能导致一些令人惊讶的结果:

using value_type = char;
template <typename T>
class Derived : public Base<T> {
  value_type func(); // this is the global value_type = char, always
};
Run Code Online (Sandbox Code Playgroud)

有关相关主题的更详尽的解释,请阅读我的中篇文章