我有以下代码,当我在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:'void AA :: setA(AA *)':无法转换 参数1来自 '的std :: _ Vector_iterator&GT;&GT;'至 'AA *'1&gt;没有可用的用户定义转换运算符 执行此转换,或者无法调用运算符
对此的简单直接修复将显式取消引用迭代器并传递给set函数,如下所示:
for (vector<AA>::iterator itr = aList.begin();
itr != aList.end(); itr++)
{
AA aa;
aa.setA(&*itr); // No error
cout << aa.geti();
}
但问题是我们在数千个源文件中有类似的代码,并且在所有文件中进行更改将非常耗时且实际上不可能。
有人可以告诉我,无论如何解决这个问题而不改变所有文件?我们可以在AA.h中做些什么来处理这个问题?
答案 0 :(得分:4)
一种选择是为当前需要指针的代码使用模板:
template <typename Iterator>
void setA(Iterator a)
{
i = a->geti();
}
唯一的缺点是,它会接受通过取消引用geti()
调用->
方法的任何内容,返回可以分配给int
的内容有效。但是,您可以使用SFINAE将其限制为类AA
。
答案 1 :(得分:1)
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
隐式转换。当您发现错误时,可以将界面中的foo*
替换为AsPointer<foo>
,并希望事情顺利进行。
如果您将NULL
传递给上述AsPointer
,则可能会抱怨 - 将其更改为nullptr
。但除此之外,它可以通过一个界面更改来解决所有呼叫站点问题。
我,我只是扫过呼叫网站。
请注意,const int*
变为AsPointer<const int>
而不是const AsPointer<int>
。