【问题标题】:Specializing a class for iterators convertable to pointers为可转换为指针的迭代器特化一个类
【发布时间】:2012-03-21 04:42:51
【问题描述】:

我正在尝试开发一个类,当它可以正确完成时,我可以通过迭代器语义有效地访问容器/指针,并且当迭代器无法转换为指针时,我想将迭代器范围复制到临时缓冲并返回该指针。为此,我编写了以下程序:

#include <cassert>
#include <vector>
#include <deque>
#include <list>

// General case copies data to temporary vector, in case iterators are from a list or otherwise.
template < typename Iterator, typename tag = std::iterator_traits < Iterator >::iterator_category >
class IteratorBuffer
{
    typedef typename std::iterator_traits < Iterator >::value_type T;

    std::vector < T > temp;
public:
    IteratorBuffer(Iterator begin, Iterator end) : temp(std::distance(begin, end)) 
    { 
        std::copy(begin, end, temp.begin()); 
    } 

    const T * data() { return temp.data(); }
};

// Special case should be invoked if Iterator can safely be treated as a pointer to the range.
template < typename Iterator >
class IteratorBuffer < Iterator, std::random_access_iterator_tag >
{
    typedef typename std::iterator_traits < Iterator >::value_type T;

    const T * temp;
public:
    IteratorBuffer(Iterator begin, Iterator end) : temp(&*begin) { }

    const T * data() { return temp; }
};

int main(int argc, char ** argv)
{
    std::vector < int > test1(10);
    IteratorBuffer < std::vector < int >::iterator > temp1(test1.begin(), test1.end());
    // This should be pointing to the data in test1.
    assert(temp1.data() == test1.data());

    std::list < int > test2;
    for(int i = 0; i < 10; ++i)
        test2.push_back(i);
    IteratorBuffer < std::list < int >::iterator > temp2(test2.begin(), test2.end());
    // This must not point to the beginning iterator.
    assert(temp2.data() != &*test2.begin());

    int test3[10];
    IteratorBuffer < int * > temp3(&test3[0], &test3[10]);
    // This should point to the array.
    assert(temp3.data() == &test3[0]);

    std::deque < int > test4;
    for(int i = 0; i < 10; ++i)
        test4.push_back(i);
    IteratorBuffer < std::deque < int >::iterator > temp4(test4.begin(), test4.end());
    // This must not point to the beginning iterator, not safe.
    assert(temp4.data() != &*test4.begin());
}

最后一次测试失败,因为 std::deque 的迭代器有 random_access_iterator_tag。

如何编写这个类以使其在一般情况下正常工作?

我想我应该提到我正在使用 VC++ 2010。

编辑:正如亚当所说(我害怕这个),这是不可能的。现在,我正在尝试定义我自己的特质,使我能够做到这一点。请参阅下面的尝试:

template < typename Iterator >
struct IteratorTraits 
{ 
    enum { IsPointerCompatible = false }; 
    typedef typename std::iterator_traits < Iterator >::value_type T;
};
template < typename T >
struct IteratorTraits < T * > 
{ 
    enum { IsPointerCompatible = true }; 
    typedef T T;
};
template < typename T >
struct IteratorTraits < const T * > 
{ 
    enum { IsPointerCompatible = true }; 
    typedef const T T;
};
//template < typename T >
//struct IteratorTraits < typename std::vector < T >::iterator > 
//{ 
//  enum { IsPointerCompatible = true };
//  typedef T T;
//};
//template < typename T, size_t N >
//struct IteratorTraits < typename std::array < T, N >::iterator > 
//{ 
//  enum { IsPointerCompatible = true };
//  typedef T T;
//};

我省略了 IteratorBuffer 类,因为它们与使用 std::iterator_traits 的类非常相似。

前两个特化有效,但两个注释特征结构将不起作用。我如何编写这些代码以使其正常工作,而不依赖于我的特定 STL 实现?

【问题讨论】:

  • &amp;*test2.begin() 看起来很丑!
  • 它很难看,但它可以工作......
  • 恐怕这不太可能。唯一的可能性是专门针对特定的迭代器,例如vector&lt;T&gt;::iterator。请注意,vector&lt;T&gt;::reverse_iterator 不安全。
  • @n.m.感谢您的评论,请参阅我对特定迭代器类的专业化的编辑。
  • 在您的专业化中,Iterator 未定义(主模板中的定义不在范围内)。您需要再次定义它:typedef typename std::vector &lt;T&gt;::iterator Iterator;。顺便说一句,typedef T T 看起来有点奇怪,虽然不是不正确的 AFAICT。无论如何我都会使用不同的标识符。

标签: c++ templates stl containers specialization


【解决方案1】:

您可以明确地专门针对指针,然后针对可以以这种方式处理迭代器的任何容器(您知道)(std::vector 就是这种情况)。这并不是那么糟糕,因为没有一个容器的一般“特征”会说它的迭代器可以用作指针。这是容器提供者必须明确做出的保证。


另请注意,IteratorBuffer 的通用版本至少默认为前向迭代器类别,并且会因仅输入迭代器而失败(因为它使用了两次范围)。

【讨论】:

  • 感谢您的回答。请参阅我的编辑,我正在尝试实现您所描述的内容,但我对如何定义特定迭代器类的专业化感到困惑。
  • 我试过了,但失败了。相信没有合理且符合标准的解决方案。但我会尝试更多,如果我能找到任何东西,我会在这里发布。
猜你喜欢
  • 2010-10-19
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2016-09-17
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 2012-07-14
相关资源
最近更新 更多