确定范围内的元素放在连续的内存中

时间:2015-03-29 20:24:04

标签: c++ templates iterator

假设我编写了处理一系列元素的模板函数。

template <typename Iter>
void func(Iter first, Iter last);

在这个函数中,我想调用一些低级别的c函数,它希望得到连续的缓冲区和它的大小。执行此操作的通用方法是将我的范围复制到连续容器,然后调用c-function。

template <typename Iter>
void func(Iter first, Iter last)
{
    typedef typename iterator_traits<Iter>::value_type value_type;
    vector<value_type> buf(first, last);
    c_func((void*) buf.data(), buf.size() * sizeof(value_type));
}

但是如果迭代器已经指向某些连续的内存空间,则会执行额外的复制。

所以问题是,有没有办法确定迭代器是否指向连续的内存空间,以及它是如何在这种情况下专门化我的函数。

1 个答案:

答案 0 :(得分:3)

目前还没有直接的方法来确定迭代器是否用于连续内存。有一个建议添加一个迭代器细化(参见例如n3884)但没有这样的东西以及一种检测为不同迭代器添加的属性的方法,你将很难确定这个特性。

需要实现者支持的关键问题是未指定迭代器类型的名称。因此,您无法创建适用于所有已知连续迭代器类型的特征。由于std::vector<T>std::array<T>的迭代器类型可以相同而且T*我认为您甚至无法创建可移植的专业化。

然而, 所做的是在特征中测试迭代器类型是否与其值类型的已知迭代器类型匹配。例如:

template <typename T, typename It>
struct test_iterator
    : std::integral_constant<bool,
        std::is_same<T*, It>::value
        || std::is_same<typename std::vector<T>::iterator, It>::value
        || std::is_same<std::string::iterator, It>::value
        || std::is_same<std::wstring::iterator, It>::value
        > {
};
template <typename It>
struct is_contiguous
    : std::integral_constant<bool,
           test_iterator<typename std::iterator_traits<It>::value_type,
                         It>::value> {
};

[我没有尝试编译代码,也就是说,它可能充斥着小错字;尽管如此,一般方法应该有效。

要添加,例如std::array<T, N>,您需要某种方式以静态方式确定维度。我猜,那不可行。可能还需要测试各种const_iterator