簡體   English   中英

auto it = vector.begin()結果類型不能轉換為const_iterator

[英]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_iteratoriterator

在從函數調用中推導出模板參數時,不考慮用戶定義的轉換,並且由於這兩個參數在這種情況下具有不同的類型,並且兩者都參與模板參數推導,因此推導失敗。

§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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM