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