簡體   English   中英

VS2013:將迭代器傳遞給帶有指針的函數(將VS2010遷移到VS2013)

[英]VS2013 : passing iterator to a function that takes pointer (migrating VS2010 to VS2013)

我有以下代碼,當我在VS2010中進行編譯時,編譯會通過,並且一切正常。

AA.h

class AA
{
    int i;
public:
    AA()
    {
        i = 0;
    }
    void setA(AA *a)
    {
        i = a->geti();
    }

    int geti()
    {
        return i;
    }
    void seti(int i)
    {
        this->i = i;
    }

};

Source.cpp

#include <vector>
#include <iostream>
#include "AA.h"
using namespace std;

int main()
{
    AA a1;
    AA a2;
    AA a3;
    a1.seti(1);
    a2.seti(2);
    a3.seti(3);
    vector<AA> aList;

aList.push_back(a1);
aList.push_back(a2);
aList.push_back(a3);

for (vector<AA>::iterator itr = aList.begin();
    itr != aList.end(); itr++)
{
    AA aa;
    aa.setA(itr); // Compiler error on VS2013
    cout << aa.geti();
}

return 0;
}

但是在VS2013中編譯相同的代碼會給我以下編譯錯誤:

Source.cpp(52):錯誤C2664:'無效AA :: setA(AA *)':無法將參數1從'std :: _ Vector_iterator >>'轉換為'AA *'1>無可用的用戶定義轉換運算符可以執行此轉換,否則無法調用運算符

一個簡單的解決方法是顯式取消對迭代器的引用,並傳遞給set函數,如下所示:

for (vector<AA>::iterator itr = aList.begin();
        itr != aList.end(); itr++)
    {
        AA aa;
        aa.setA(&*itr); // No error
        cout << aa.geti();
    }

但是這里的問題是,我們在成千上萬個源文件中都有類似的代碼,並且對所有文件進行更改將非常耗時並且實際上是不可能的。

有人可以告訴我是否有解決方法而不更改所有文件嗎? 我們可以在AA.h中做些什么來解決這個問題?

一種選擇是對當前需要使用指針的代碼使用模板:

template <typename Iterator>
void setA(Iterator a)
{
    i = a->geti();
}

唯一的缺點是它將接受通過取消引用對geti()方法的調用->返回可以分配給int內容有效的任何內容。 但是您可以使用SFINAE技巧,將其限制為AA類。

template<typename T>
struct AsPointer {
  T* p;
  operator T*() const { return p; }
  T* operator->() const { return p; }
  T& operator*() const { return *p; }
  explicit operator bool() const { return p; }
  AsPointer():p(nullptr) {}
  AsPointer(AsPointer const&)=default;
  AsPointer(AsPointer&)=default;
  AsPointer(AsPointer const&&)=default;
  AsPointer(AsPointer&&)=default;
  // sfinae may not work here, but at least you get an error:
  template<typename U,typename=typename std::iterator_traits<typename std::decay<U>::type>::iterator_category>
  AsPointer(U&& u):p(&*u) {}
  template<typename U>
  AsPointer(U* u):p(u) {}
  AsPointer(std::nullptr_t):p(nullptr) {}
};

是一個template偽指針,可以像對待指針一樣對待,但也可以從任何iterator隱式轉換。 當發現錯誤時,可以使用AsPointer<foo>替換接口中的foo* ,希望一切順利。

如果將NULL傳遞給上述AsPointer ,則可能會抱怨-將其更改為nullptr 但是除此之外,通過一個界面更改,它就可以解決您所有的呼叫站點問題。

我,我只是打掃電話站點。

請注意, const int*成為AsPointer<const int>而不是const AsPointer<int>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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