C ++:对std :: vector迭代器进行offseting的正确转换是什么?

时间:2017-06-11 05:51:26

标签: c++ c++11 vector offset static-cast

我有一个函数需要std::vector个双精度数,并将它们复制到另一个向量,但是在一个特定的偏移处(假设有足够的空间):

void copy_stuff(const std::vector<double> & data,
                std::vector<double> & dest,
                size_t dest_offset) {
    std::copy(data.begin(), data.end(), dest.begin() + dest_offset);
}

这会导致以-Weverything部分为中心的C ++ 11 clang编译器+ dest_offset警告:

  

隐式转换更改了签名:'size_t'(又名'unsigned long')到'difference_type'(又名'long')。

我不确定如何转换表达式dest.begin() + dest_offset以消除此警告。将结果转换为double *不会编译:

    std::copy(data, data + data_size, static_cast<double *>(dest.begin() + dest_offset));
  

无法从'std :: __ 1 :: __ wrap_iter'类型转换为指针类型'double *'。

我曾考虑使用矢量索引,然后使用地址:

    std::copy(data, data + data_size, &dest[dest_offset]);

这似乎消除了这种情况下的警告,但如果我尝试使用与源向量相同的模式,即在std::copy的第一个或第二个参数中涉及偏移,则不会编译。例如:

static void copy_stuff_differently(const std::vector<double> & data,
                                   std::vector<double> & dest,
                                   size_t offset) {
    std::copy(data.begin() + offset, data.end(), dest.begin());
}

+ offset上提供隐式转换的原始警告。尝试使用索引地址可能会建议:

    std::copy(&data[offset], data.end(), dest.begin());

或者是一个不同但相似的案例:

    std::copy(data.begin(), &data[offset], dest.begin());

但是两者都会导致类似的错误:

test.cpp:8:3: error: no matching function for call to 'copy'
  std::copy(&data[offset], data.end(), dest.begin());
  ^~~~~~~~~
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:1286:48: note:
      candidate template ignored: deduced conflicting types for parameter '_Ip' ('const double *' vs.
      'std::__1::__wrap_iter<const double *>')
    template <class _Ip, class _Op> friend _Op copy(_Ip, _Ip, _Op);
                                               ^

我正在寻找一种一致且无警告的方法来处理这种偏移。将偏移量处理为向量并避免此类错误和警告的正确方法是什么?

2 个答案:

答案 0 :(得分:4)

  

我不确定如何强制转换表达式dest.begin() + dest_offset以消除此警告。

警告只是告诉您dest_offset应该属于std::vector::difference_type类型,但它是size_t

您可以显式执行转换以消除警告(请注意,如果源值无法在difference_type中表示,则结果是实现定义的)。 e.g。

dest.begin() + static_cast<std::vector<double>::difference_type>(dest_offset)

或者从头开始使用类型dest_offset声明参数difference_type

请注意,std::vector::difference_type是有符号整数类型(通常为std::ptrdiff_t),与size_t不同;这是一个无符号整数类型。

答案 1 :(得分:4)

您可以使用部分 difference_type来避免此警告:

#include<vector>

using difference_type = std::vector<double>::difference_type;

void copy_stuff(const std::vector<double> & data,
                std::vector<double> & dest,
//                size_t dest_offset)
                difference_type dest_offset)
{
    std::copy(data.begin(), data.end(), dest.begin() + dest_offset);
}

现在广泛接受[引证需要]报告/使用大小和一些偏移作为无符号整数类型在标准库的设计中是错误的。 因此,在我看来,最好不要遵循该约定并尽快从标准库中转换无符号类型,而不是调整函数以使用无符号类型。

例如copy_stuff(a.begin(), a.end(), static_cast<difference_type>(other.size()) )