我正在编写一个实用程序函数,它将采用元素向量(可以是string,int,double,char)并连接成一个字符串并返回它。它看起来像这样:
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();
}
我想让这个功能更通用:
vector<T>
的索引。我试过这个
在循环之前std::vector<T>::const_iterator it = vec.begin()
并且编译器给了我一个错误:
:错误:预期;
之前
当我将上述定义更改为std::vector<std::string>::const_iterator it = vec.begin()
时,错误消失了。所以,看起来我没有遵循正确的语法,请让我知道它是什么vector
,list
,queue
,deque
等)我想做与上面相同的事情。我尝试在stackoverflow中搜索这个并没有找到满意的答案。答案 0 :(得分:5)
第1步,如你所说,使用迭代器:
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();
}
步骤2,使模板参数成为容器类型而不是元素类型(您可以使用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();
}
在C ++ 0x中,这变得更简单(并且不需要typename
):
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();
}
除其他优点外,std::begin
和std::end
适用于原始数组。
答案 1 :(得分:5)
遵循STL练习,我建议使用两个迭代器作为输入参数,而不是容器(因为明显的原因是只能使用容器的一部分,通常使用迭代器定义的任何序列):
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();
}
如果您需要包含对象的类型,请使用
typedef typename std::iterator_traits<InputIterator>::value_type T;
增加: 然后,您可以按如下方式使用该功能:
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;
请注意,您无法遍历std :: queue;但如果您确实需要它,该标准可确保为自己动手解决方案提供足够的支持。在此处查看更多信息:std::queue iteration。
答案 2 :(得分:3)
如果你只对容器类型进行模板化,这是最简单的;值类型作为typedef
成员value_type
存储在所有标准Boost和Qt容器中。 std::copy
和ostream_iterator
允许您跳过冗长的迭代器声明。
template <typename Container>
std::string convert2Str(Container const &cont)
{
std::ostringstream s;
std::copy(cont.begin(), cont.end(),
std::ostream_iterator<typename Container::value_type>(s, " "));
return s.str();
}
typename
是避免歧义所必需的。当您省略此关键字时,最新版本的GCC会发出警告。
答案 3 :(得分:2)
使用它。你需要typename
部分来告诉编译器它在解析时应该考虑T::const_iterator
一个类型,它实际上不能知道这是真的,直到你实际调用函数传递一些{{1有T
成员类型。
const_iterator
答案 4 :(得分:0)
我认为这应该有效:
template<typename T>
std::string convert2Str(T const& container)
{
std::ostringstream sStream;
for (typename T::const_iterator i= container.begin(); i != container.end(); ++i) {
sStream << *i << " ";
}
return sStream.str();
}