使用模板来克服缺乏基类的问题
Use template to overcome the lack of a base class?
显然,标准容器既没有公共的基类,也没有公共的接口,尽管方法名是同质的。
问题:我必须用唯一类型的对象集合填充容器。容器可以是std::list
、std::vector
或std::deque
,也可能是其他一些自定义容器。下面的代码是最佳解决方案吗?
# include <string>
# include <iostream>
# include <list>
# include <vector>
# include <deque>
/*
* Fill a container with two strings. The container
* must expose the `clear` and `push_back` methods.
*/
template<typename T>
void f(T & t)
{
t.clear() ;
t.push_back("Alice") ;
t.push_back("Bob") ;
}
int main(int, char*[])
{
std::list<std::string> l ;
std::vector<std::string> v ;
std::deque<std::string> q ;
f(l) ; // fill the list
f(v) ; // fill the vector
f(q) ; // fill the double-ended queue
// possibly anything with `clear` and `push_back` methods
// can be filled with `f`
return 0 ;
}
谢谢你的建议!
编辑
这是我在第一篇文章中用f
说明的情况:
struct AudioFormat
{
uint32_t samplerate ; // Sampling frequency
uint8_t channels ; // The number of channels
uint8_t bitdepth ; // The number of bits per sample
} ;
class AudioDevice
{
// many stuff skipped
public :
/*
* Fills the container with available audio formats handled properly by the device
*/
void GetSupportedAudioFormats(std::list<AudioFormat> &) ;
// many stuff skipped
} ;
我正在寻找一种更好的方法来声明GetSupportedFormats
,这样它就可以处理许多其他容器,而不仅仅是std::list
s。
我的最爱是:
/*
* Fill a container with two strings. The container
* must expose the `clear` and `push_back` methods.
*/
template<typename T>
void f(T & t)
{
t.clear() ;
std::insert_iterator<T> it(t, t.end());
*it++ = "Alice";
*it++ = "Bob";
}
现在的约束是:clear
和insert
,所以它也可以与std::set
一起工作。此外,它可以与任何类型的工作,你只需要专门为它的std::insert_iterator
模板。
这是一个解决方案。
一个更"STL"风格的解决方案是使用std::back_inserter
char const* names[2] = { "Alice", "Bob" };
std::list<std::string> l;
std::vector<std::string> v;
std::deque<std::string> q;
std::copy(names, names+2, std::back_inserter(l));
std::copy(names, names+2, std::back_inserter(v));
std::copy(names, names+2, std::back_inserter(q));
使用clear()和add()方法提供您自己的抽象类
class ContainerIterface
{
public:
virtual void clear() = 0;
virtual void add(const UniqueType &e) = 0;
};
然后你可以推导出像
这样的东西template <typename Container>
class TemplatedContainer : public ContainerIntarface {
virtual void clear() {c_.clear();}
virtual void add(const UniqueType &e) {std::inserter(c_, c_.end()) = e;}
private:
Container c_;
};
这假定在容器中只有一种类型要存储。如果不是这样,基类也会变成模板,派生类需要模板参数是模板(std::vector
而不是std::vector<UniqueType>
)
相关文章:
- 我是否需要在虚拟继承类的构造函数中初始化基类以解决菱形继承问题?
- 关于C++从派生类调用在基类中实现的虚拟函数的问题
- 为什么不允许在非推导上下文中使用基类定义,以及如何解决这个问题
- 类型特征检查 CRTP 派生,在基类中,问题是未定义的类型
- 试图在具有std ::任何构造函数的基类中调用复制构造函数的问题
- 分配派生类的对象时出现问题,其中基类具有抽象虚函数
- 纯基类 c++ 的动态数组出现问题
- C++编译器错误基类问题
- 基类的复制构造函数的可见性问题
- 设计问题迫使我将基类向下转换为派生类型
- 将抽象基类作为成员处理时的所有权问题
- VS2013 在未命名命名空间中遇到基类问题
- 模板类和继承问题 - 'List'不命名非静态数据成员或基类
- 设计问题,基类知道它的导数
- 从派生类调用基类函数时出现问题
- 继承基类时遇到问题
- 验证我的超类或基类是宏或模板声称的那个类时出现问题
- 子类到基类的转换问题
- C++从基类继承的多个类会导致问题
- 强制转换基类问题