【问题标题】:How to use templated iterators when value type of iterator is not know for a generalised STL Container?当不知道通用 STL 容器的迭代器的值类型时,如何使用模板化迭代器?
【发布时间】:2016-08-23 06:36:41
【问题描述】:

我想写一个模板化函数

  • 接受 2 个迭代器
  • 使用 *copy(在算法标准头文件中定义)打印存储在容器中的内容。

这是我写的一段代码,但会产生编译错误

template <template<typename, typename> class Container, 
            typename Value, 
            typename Allocator = std::allocator<Value> >
void printContainer(Container<Value, Allocator>::iterator itBegin,
                    Container<Value, Allocator>::iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<Value>(cout, " "));
        cout << endl;
}

产生的错误是:

  error 1: variable or field ‘printContainer’ declared void
  void printContainer(Container<Value, Allocator>::iterator itBegin,
                                                   ^
  error 2: expected ‘)’ before ‘itBegin’
  void printContainer(Container<Value, Allocator>::iterator itBegin,
                                                            ^
  error 3: expected ‘)’ before ‘itEnd’
       Container<Value, Allocator>::iterator itEnd)
                                             ^
 p00441.cpp: In function ‘int main()’:
 p00441.cpp:10:39: error: ‘printContainer’ was not declared in this scope
   printContainer(inp.begin(), inp.end());

我写的另一个sn-p是

template<typename InputIterator>
void printContainer(InputIterator itBegin, InputIterator itEnd){
        //Trial 1
        copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));

        //Trial 2
        copy(itBegin, itEnd, ostream_iterator<value_type(itBegin)*>(cout, " "));
        cout << endl;
}

产生的错误是:

error 1: ‘ForwardIterator1’ was not declared in this scope
   copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));
                                                          ^
error 2: template argument 1 is invalid
   copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));
                                                                          ^
error 3: template argument 1 is invalid
   copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));
                                                                                       ^
error 3: type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp, class _CharT, class _Traits> class std::ostream_iterator’
   copy(itBegin, itEnd, ostream_iterator<value_type(itBegin)*>(cout, " "));
                                                             ^
error 4:   expected a type, got ‘(value_type(itBegin) * <expression error>)’

请详细说明错误的含义及其发生原因。还建议如何实现预期目标。

如果您能为新手提供一些了解迭代器的资源,我将不胜感激。

【问题讨论】:

  • 我不完全清楚为什么 ContainerAllocator 甚至是模板类型参数的一部分。不只是Iterator 工作吗?您仍然可以通过std::iterator_traits 破译它的值类型。
  • @WhozCraig Container 被使用,这样我就可以传递对通用容器的引用并使用 container.size() 来显示所有元素。但是迭代器更方便。

标签: c++ templates stl iterator


【解决方案1】:

关于您的第一个问题,您可以简单地使用迭代器作为模板类型并使用iterator::value_type

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename Iterator>
void printContainer(Iterator itBegin,
                    Iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<typename Iterator::value_type>(cout, " "));
        cout << endl;
}

int main() {
    vector<int> v{1, 2, 3, 4, 5, 6};
    list<int>   l{1, 2, 3, 4, 5, 6};
    printContainer(begin(v), end(v));
    printContainer(begin(l), end(l));

    return 0;
}

https://ideone.com/DhUQ1t

使用iterator_traits 也有效,并且是更好的解决方案,因为它也适用于指针(自然没有value_type 成员;感谢Jarod42 指出这一点):

template <typename Iterator>
void printContainer(Iterator itBegin,
                    Iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<typename iterator_traits<Iterator>::value_type>(cout, " "));
        cout << endl;
}

https://ideone.com/8N0ook

从C++14开始,还可以使用decltypedecay_t

template <typename Iterator>
void printContainer(Iterator itBegin,
                    Iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<decay_t<decltype(*itBegin)>>(cout, " "));
        cout << endl;
}

https://ideone.com/7MBsiL


关于您的其他尝试,您的函数中没有定义ForwardIterator1value_typetypedef,而不是函数。

【讨论】:

  • iterator_traits 优于 Iterator::value_type,因为前者适用于常规指针。
  • decay_t 可以与decltype 一起使用以获得等效代码。
  • @Jarod42:感谢您指出这些事情。我已经更新了第一个,但我不确定第二个:decay 有什么用?
  • @rainer decltype(*itBegin) 将返回 (const-qualified) 对 value_type(const) value_type&amp; 的引用 - 如果您只想要 value_type,则需要删除引用和 (可能)const-qualification,这就是 std::decay_t 所做的。
  • @rainer 谢谢你和所有帮助我解决这个问题的人。现在我可以更多地关注问题,而不仅仅是打印 Container :)
猜你喜欢
  • 2014-09-10
  • 1970-01-01
  • 2021-07-29
  • 2012-05-10
  • 2018-06-11
  • 1970-01-01
  • 2013-04-16
  • 2012-11-18
  • 1970-01-01
相关资源
最近更新 更多