显然,标准容器没有公共基类,也没有通用接口,尽管方法名称是同构的。
问题:我必须使用一组唯一类型的对象填充容器。容器可以是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。这是我第一篇文章的重点。
答案 0 :(得分:6)
我最喜欢的是:
/*
* 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
模板。
答案 1 :(得分:3)
这是一个解决方案。
更“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));
答案 2 :(得分:1)
使用方法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_;
};
这假设您只有一种类型存储在容器中。如果不是这样,你的基类也变成了一个temaplate,派生类需要一个模板参数作为模板(std::vector
而不是std::vector<UniqueType>
)