[英]How to store the vector.begin() iterator of template type in thrust?
[英]auto it = vector.begin() resulting type is not convertible to const_iterator
容器需要提供iterator
類型,該類型可以隱式轉換為const_iterator
。 鑒於此,我試圖使用auto
通過vector::begin()
初始化一個對象,並在std::distance
中使用該結果對象,其中RHS是一個const_iterator
。 這不起作用。 這是一個完整的例子:
#include <cstdlib>
#include <vector>
#include <iterator>
#include <iostream>
typedef std::vector <char> Packet;
typedef std::vector <Packet> Packets;
template <typename Iter>
Iter next_upto (Iter begin, Iter end, size_t n)
{
Iter ret = begin;
for (; n > 0 && ret != end; ++ret, --n)
;
return ret;
}
Packets::const_iterator Process (Packets::const_iterator begin, Packets::const_iterator end)
{
Packets::const_iterator ret = begin;
while (ret != end)
++ret; // do something
return ret;
}
int main()
{
Packets test (100); // vector of 100 default-initialized packets
// process them 10 at a time
for (auto it = test.begin();
it != test.end();
it = next_upto (it, test.end(), 10))
{
auto itr = Process (it, next_upto (it, test.end(), 10));
Packets::const_iterator it2 = it;
const size_t n1 = std::distance (it2, itr);
const size_t n = std::distance (it, itr);
std::cout << "Processed " << n << " packets\n";
}
}
在g ++ 4.8.1(和4.8.2)下編譯,得到:
[1/2] Building CXX object CMakeFiles/hacks.dir/main.o
FAILED: /usr/bin/g++ -Wall -std=c++11 -g -MMD -MT CMakeFiles/hacks.dir/main.o -MF "CMakeFiles/hacks.dir/main.o.d" -o CMakeFiles/hacks.dir/main.o -c main.cpp
main.cpp: In function ‘int main()’:
main.cpp:39:45: error: no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<std::vector<char>*, std::vector<std::vector<char> > >&, __gnu_cxx::__normal_iterator<const std::vector<char>*, std::vector<std::vector<char> > >&)’
const size_t n = std::distance (it, itr);
^
main.cpp:39:45: note: candidate is:
In file included from /usr/include/c++/4.8/bits/stl_algobase.h:66:0,
from /usr/include/c++/4.8/vector:60,
from main.cpp:2:
/usr/include/c++/4.8/bits/stl_iterator_base_funcs.h:114:5: note: template<class _InputIterator> typename std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator, _InputIterator)
distance(_InputIterator __first, _InputIterator __last)
^
/usr/include/c++/4.8/bits/stl_iterator_base_funcs.h:114:5: note: template argument deduction/substitution failed:
main.cpp:39:45: note: deduced conflicting types for parameter ‘_InputIterator’ (‘__gnu_cxx::__normal_iterator<std::vector<char>*, std::vector<std::vector<char> > >’ and ‘__gnu_cxx::__normal_iterator<const std::vector<char>*, std::vector<std::vector<char> > >’)
const size_t n = std::distance (it, itr);
^
我知道,我可以通過調用解決這種特定情況下cbegin()
和cend()
而不是begin()
和end()
,但由於begin()
和end()
返回一個類型,應該是轉換為const_iterator
,我我不確定我理解為什么需要它。
為什么auto
在這種情況下推斷出一種不能轉換為const_iterator
?
您的問題可以簡化為以下示例,由於相同的原因,該示例失敗。
#include <vector>
#include <iterator>
int main()
{
std::vector<int> v;
std::vector<int>::const_iterator it1 = v.begin();
auto it2 = v.end();
auto n = std::distance(it1, it2);
}
std::distance
是使用兩個參數的相同模板參數類型定義的,並且模板參數推斷失敗,因為您有一個const_iterator
和iterator
。
在從函數調用中推導出模板參數時,不考慮用戶定義的轉換,並且由於這兩個參數在這種情況下具有不同的類型,並且兩者都參與模板參數推導,因此推導失敗。
§14.8.1/ 6 [temp.arg.explicit]
如果參數類型不包含參與模板參數推導的模板參數 ,則將對函數參數執行隱式轉換(第4節)以將其轉換為相應函數參數的類型。
§14.8.2.1/ 4 [temp.over]
...
[ 注意:如14.8.1中所述,如果參數不包含參與模板參數推導的模板參數 ,則將對函數參數執行隱式轉換,以將其轉換為相應函數參數的類型。 除了前面列表中描述的轉換之外,還允許這樣的轉換。 - 尾注 ]
您需要將iterator
轉換為const_iterator
,或者將模板參數明確指定為std::distance
。
auto n = std::distance(it1, static_cast<decltype(it1)>(it2));
要么
auto n = std::distance<decltype(it1)>(it1, it2);
當然,其他選項是不使用auto
並在兩種情況下顯式指定迭代器類型,或者在需要確保類型為const_iterator
時使用vector::cbegin()
和vector::cend()
vector::cbegin()
vector::cend()
成員函數。
這個問題與迭代器轉換沒什么共同之處。 編譯器無法確定模板參數。 你寫的也是一樣的
int x = 10;
long y = 20;
std::cout << std::max( x, y ) << std::endl;
雖然int
類型的對象可以隱式轉換為long
類型的對象。
至於你的例子,你可以寫
const size_t n = std::distance<std::vector<char>::const_iterator> (it, itr);
為什么自動推斷出一個典型[在這種情況下不能轉換為const_iterator?
begin()
有兩個可用的重載: 簽名:
iterator begin();
const_iterator begin() const;
你將你的向量聲明為Packets test (100);
,這是非常數。
如果將其聲明為const,則auto
類型推導將使第二個begin()
重載作為最佳(和唯一)匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.