Obviously, standard containers don't have a common base class, nor a common interface, although the method names are homogeneous.
The problem : I have to fill a container with a collection of objects of a unique type. The container can be a std::list
, a std::vector
or a std::deque
, and possibly some other custom container. Is the following code the best solution ?
# 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 ;
}
Thanks for any advice !
EDIT
Here is the case that I illustrated with f
in my first post :
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
} ;
I am looking for a better way to declare GetSupportedFormats
so it can handle many other containers, not only std::list
s. That's the point of my first post.
My favorite would be:
/*
* 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";
}
The constraints are now: clear
and insert
, so it will also work with std::set
for example. Also, it could work with any type, you would just have to specialise the std::insert_iterator
template for it.
That's one solution.
A more "STL" style solution is to use a 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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With