2017-06-11 36 views
3

我有一个函数,它双打的std::vector,并将它们复制到另一个载体,但在特定的偏移量(假设有足够的空间):C++:退出到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); 
} 

这导致C++ 11铛编译器-Weverything警告集中在+ dest_offset部分:

Implicit conversion changes signedness: 'size_t' (aka 'unsigned long') to 'difference_type' (aka 'long').

我不知道我应该怎么投,以消除此警告的表达dest.begin() + dest_offset。结果强制转换为double *不会编译:

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

Cannot cast from type 'std::__1::__wrap_iter' to pointer type '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); 
              ^

我寻找一种一致的,无警告的方式来处理这种偏移。什么是正确的方式来处理向量的偏移并避免这样的错误和警告?

+1

铿锵声开发人员非常明确地说,你应该不***使用 - 万物。 –

+0

'std :: next(std :: begin(),dest_offset)'改变什么? –

回答

3

I'm not sure how I should cast the expression dest.begin() + dest_offset in order to eliminate this warning.

的警告只是告诉你,dest_offset预计类型std::vector::difference_type的,但它是size_t

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

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

或者从一开始的类型difference_type声明参数dest_offset

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

+6

我想说的参数应该是'std :: vector :: difference_type'而不是'size_t'开头。 –

+0

'std :: next(dest.begin(),dest_offset)'避免了警告吗?我现在没有铿锵声来测试它。 – Blastfurnace

+0

@Blastfurnace'std :: next'也需要一个'difference_type'。 – songyuanyao

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()))

+0

谢谢,我会考虑使用这个 - 最初的实验表明,它确实使很多警告消失。 – meowsqueak

+0

你不应该再检查一下'dest_offset> = 0吗? – Walter

+0

@Walter不幸的是,认为这是一个错误,因为该类型是未签名的,它保证了正面的价值是有道理的。如果你输入一个负数来运作,它会将它转换成一个大的正数,这也是没有意义的。你使用无符号类型做的唯一的事情就是隐藏错误。我说“不幸”,因为它具有数学意义,但实际上它不起作用,因为“无符号类型”实际上是“模数类型”的错误名称。您可以添加该检查,但它有成本,最好确保程序逻辑有意义。 – alfC

相关问题