对于(无论如何对于我的水平而言)相当复杂的模板问题,我将不胜感激。
让我先解释一下我的“系统”。
模拟一个基本的音频混合和流媒体系统,它包含三个构建组件:
Buffer,Player 将从中处理数据。
由于它们直接由数据连接,因此它们的数据需要属于同一类型。因此 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);
}
};
关于C++模板问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39876363/