I'm writing a utility function which will take a vector of elements (could be string, int, double, char) and concatenate into a single string and return it. It looks like this:
template<typename T>
std::string convert2Str(std::vector<T> const& vec)
{
std::ostringstream sStream;
for (size_t k=0; k<vec.size(); ++k) {
sStream << vec[k] << " ";
}
return sStream.str();
}
I would like to make this function more generic:
vector<T>
. I tried this
std::vector<T>::const_iterator it = vec.begin()
before the loop and the compiler gave me an error:
: error: expected ;
before it
When I change the above defintions to std::vector<std::string>::const_iterator it = vec.begin()
the error goes away. So, it looks like I'm not following correct syntax, please let me know what it is vector
, list
, queue
, deque
, etc.) I want to do the same thing as above. I tried searching for this in stackoverflow and did not find satisfactory answer.A container can contain anything, from a webservice, to a million LOC monolith, to a complete DBMS system, to the data tier that DBMS writes into. These containers can live forever, scale horizontally (or not), take 20 minutes to start, 20 days to run, and on and on. Contrast this to a Function, which typically has a set of known characteristics:
Now if we take our function with these characteristics and package it into a container, then we can now think and reason about that container differently, giving rise to a powerful concept-a new atomic unit of compute.
Although a function is likely just part of a broader grouping of functions (eg. many functions create an API, a sequence of functions create a “flow”), by itself, it can run independently as long as it gets its required input. [thanks Tobias Kunze for name suggestion]
Step 1, as you said, use iterators:
template<typename T>
std::string convert2Str(std::vector<T> const& vec)
{
typedef std::vector<T> container;
std::ostringstream sStream;
for (typename container::const_iterator it = vec.begin(); it != vec.end(); ++it) {
sStream << *it << " ";
}
return sStream.str();
}
Step 2, make the template argument the container type instead of the element type (you can get the element type back with value_type
:
template<typename container>
std::string convert2Str(container const& vec)
{
typedef container::value_type T; // if needed
std::ostringstream sStream;
for (typename container::const_iterator it = vec.begin(); it != vec.end(); ++it) {
sStream << *it << " ";
}
return sStream.str();
}
In C++0x, this gets even simpler (and typename
is not needed):
template<typename container>
std::string convert2Str(container const& vec)
{
using std::begin;
using std::end;
std::ostringstream sStream;
for (auto it = begin(vec); it != end(vec); ++it) {
typedef decltype(*it) T; // if needed
sStream << *it << " ";
}
return sStream.str();
}
Among other advantages, std::begin
and std::end
work for raw arrays.
Following STL practice, I would recommend using two iterators for input parameters, instead of a container (for obvious reason of being able to work with only a part of a container, and generally with any sequence defined by iterators):
template<typename InputIterator>
std::string convert2Str(InputIterator first, InputIterator last)
{
std::ostringstream sStream;
for (InputIterator it = first; it != last; ++it) {
sStream << *it << " ";
}
return sStream.str();
}
In case you need the type of contained objects, use
typedef typename std::iterator_traits<InputIterator>::value_type T;
ADDED: You then can use the function as follows:
std::vector<int> int_vec;
std::list<float> f_list;
std::deque<std::string> str_deq;
// put something into the containers here
std::cout<< convert2Str(int_vec.begin(), int_vec.end()) <<std::endl;
std::cout<< convert2Str(f_list.begin(), f_list.end()) <<std::endl;
std::cout<< convert2Str(str_deq.begin(), str_deq.end()) <<std::endl;
Note that you cannot iterate over std::queue; but if you really need it, the standard guarantees enough support for a do-it-yourself solution. See more info here: std::queue iteration.
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