如何从输出迭代器中获取值类型?

101*_*010 12 c++ iterator stl c++03

假设我有一个C容器(例如MyContainer),其中包含的对象存储为void*指针.迭代此容器元素的唯一方法是通过两个接口函数:

  1. getFirstElem(MyContainer const&, void*):输出容器的第一个元素.
  2. getNextElem(MyContainer const&, void*):输出容器的下一个元素.

我想编写一个泛型函数,它通过上面提到的接口函数遍历这个C容器的元素,并将它们的值复制到C++容器中(例如std::vector).

到目前为止我做了什么:

template<typename OutputIterator>
void
copy_container(MyContainer const &cont, OutputIterator first) {
  typename std::iterator_traits<OutputIterator>::value_type elem;
  if(getFirstElem(cont, &elem)) {
    do {
      *first = elem;
      ++first;
    } while(getNextElem(cont, &elem))    
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的示例适用于普通迭代器.但是,它无法使用输出迭代器进行编译(例如,copy_container(cont, std::back_inserter(myvector));).

原因是在参数类型是输出迭代器的情况下std::iterator_traits::value_type导致结果void.

有没有办法让这个泛型函数也适用于输出迭代器?

我知道在C++ 11中它可以通过使用decltype(例如decltype(*first))来完成,但我对C++ 11之前的解决方案特别感兴趣,因为我使用旧的C++编译器(gcc v4.4.7).

Nik*_*iou 8

正确观察,value_type输出迭代器是void.除了替换这个之外没什么可做的:

typename std::iterator_traits<OutputIterator>::value_type elem;
Run Code Online (Sandbox Code Playgroud)

有了这个

decltype(*first) elem;
Run Code Online (Sandbox Code Playgroud)

(即使标准不保证它可以工作 - 可以通过取消引用输出迭代器来返回代理).

正如您所说,没有C++ 11解决方案,因此可能需要进行重新设计.以下是一些选项:

1.通过容器

您可以将引用传递给容器,而不是第一个元素的迭代器.看起来你想要的只是一个push_back.

template<template<typename,typename> class stlContainer>
void copy_container(
    MyMontainer const &cont, OutputIterator first) 
{ 
    // insertion in stlContainer
Run Code Online (Sandbox Code Playgroud)

那么你所需要的只是一层特征,可以调度到每个容器的正确插入实现

2.传递额外的模板参数

值类型可以是额外的模板参数.

template<typename value_type, typename OutputIterator>
void copy_container(MyMontainer const &cont, OutputIterator first) 
{
    value_type elem;
...
Run Code Online (Sandbox Code Playgroud)


Jar*_*d42 5

您可以使用 typetraits 和专业化

template <typename IT>
struct it_value_type
{
    typedef typename std::iterator_traits<IT>::value_type elem;
};

template <typename Container>
struct it_value_type<std::back_insert_iterator<Container>>
{
    typedef typename Container::value_type elem;
};

template <typename Container>
struct it_value_type<std::front_insert_iterator<Container>>
{
    typedef typename Container::value_type elem;
};
Run Code Online (Sandbox Code Playgroud)

然后你的代码变成:

template<typename OutputIterator>
void
copy_container(MyContainer const &cont, OutputIterator first) {
    typename it_value_type<OutputIterator>::elem elem;
    if (getFirstElem(cont, &elem)) {
        do {
            *first = elem;
            ++first;
        } while (getNextElem(cont, &elem));
    }
}
Run Code Online (Sandbox Code Playgroud)