C++模板问题

标签 c++ templates generics inheritance interface

对于(无论如何对于我的水平而言)相当复杂的模板问题,我将不胜感激。

让我先解释一下我的“系统”。

模拟一个基本的音频混合和流媒体系统,它包含三个构建组件:

BufferPlayer 将从中处理数据。 由于它们直接由数据连接,因此它们的数据需要属于同一类型。因此 Buffer<T> ~ Player<T> ,这里的模板必须匹配。

这些都包裹在 Manager 中,他最终会将所有传入的缓冲区管理到一个播放器中。

现在,缓冲区和播放器都需要一些不同的实现,因此它们由通用接口(interface)表示为 iPlayer 和 iBuffer。

我的目标是能够像这样声明一个管理器:

simple_manager<simple_player<float>>;

或至少失败

simple_manager<simple_player , float>;

因为我不确定第一个是否有解决方案,所以我对第二个的尝试是这样的:

template <typename K>
class iManager {
    private:
        K player;
};

template <template <typename> class C , typename T>
class simple_manager : iManager< C<T> > {
    public:
        void play(iBuffer<T> & _buffer,const audio_descriptor ad, bool * condition){
            player.play(_buffer,ad,condition);
        }


};

如您所见,在具体类中,T 标记要操作的数据类型,而 C 是我希望使用的播放器的具体类。 该接口(interface)只有一个模板,再次标记具体的播放器类。所以K ~ C<T>

这不会编译(仅)出现以下错误:

simple_manager.cpp: In member function ‘void simple_manager<C, T>::play(iBuffer<T>&, audio_descriptor, bool*)’:
simple_manager.cpp:18:12: error: ‘player’ was not declared in this scope
            player.play(_buffer,ad,condition);
            ^~~~~~

我不知道是什么原因造成的。编译器不能推断出 T 必须继承自 iPlayer,因为 iPlayer 必须实现一个 play() 方法。

如果我这样定义 simple_manager,我可以让它真正工作:

class simple_manager : iManager< simple_player<float> > {...}

但它仍然无法工作:

class simple_manager : iManager< simple_player<T> > {...}

我被难住了。如果我有 <T extends iPlayer>在 Java 中,这会起作用,但我猜想编译时模板化是一个更难的问题。

如有任何帮助,我们将不胜感激!

最佳答案

第一个问题是 player无法从派生类访问,因为它被标记为 private而不是 protected .你可以做到 protected或添加一些 protected访问它的成员函数:

template <typename K>
class iManager {
protected:
    K player;
};

但是,这仍然行不通,因为 iManager<C<T>>是一个依赖基类,因此它的成员在不合格的名称查找中是隐藏的。要解决此问题,您可以通过 this 访问它。指针:

void play(iBuffer<T> & _buffer,const audio_descriptor ad, bool * condition){
    this->player.play(_buffer,ad,condition);
}

为了在您的第一个示例中获得良好的用法,您可以编写一个特征来从给定类型中提取模板参数:

template <typename T> struct extract_inner;

template <template <typename> class C, typename T> 
struct extract_inner<C<T>> { using type = T; };

template <typename T> 
using extract_inner_t = typename extract_inner<T>::type;

然后可以用来为 iBuffer 提供正确的参数:

template <typename T>
class simple_manager : iManager< T > {
public:
    void play(iBuffer<extract_inner_t<T>> & _buffer,
              const audio_descriptor ad, bool * condition){
        this->player.play(_buffer,ad,condition);
    }
};

Live demo

关于C++模板问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39876363/

相关文章:

c++ - CGAL:延伸线段直到多边形边界

c# - 在 C# 中,是否有通用方法将 DBSet 传递给方法?

java - 枚举的泛型和 builder 模式

c++ - 安全的、密码特定的 std::string 在解除分配时将自身归零

generics - Scala:在泛型类中进行数字运算的最佳方法是什么?

c++ - 合并头文件和cpp文件

c# - 检测图像中的圆形图案

C++:防止在 const 函数中更改指针的值

c++ - 嵌套模板 C++

c++ - 模板化重载运算符的编译错误 "No global operator found"