I am working on a project that stopped compiling properly after an unwanted compiler update (long story). I am using the latest Visual Studio C++ compiler (free edition).
I figured out how to get it to compile again but I do not understand why I had to do what I did in order to make it work again.
I extracted and simplified the code so it can be reproduced and easily identified.
I tracked it down to one issue: The scoping rules changed on me after the compiler update.
Below is the old code I converted (in namespace OldCode).
Note how I can access the member variable 'x' and 'y' directly.
Following is the template code (in namespace NewCode).
I can no longer access 'x' or 'y' directly.
Now I must use this-> or baseclass:: in order to access it.
remember: This compiled clean before. After the update it does not.
Were some rules tightened? Was the compiler not up to spec before? Or should the code still work and this is some sort of bug? Or am I not understanding what is going on here?
The line of code is just after the comment:
//****** What's going on here?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
namespace OldCode {
// This is the code I converted to use a template.
// Note that I can refer to 'x' and 'y' directly
// in Point::operator= without using this->
struct _tagPOINT
{
int x;
int y;
_tagPOINT(int a, int b) :x(a), y(b) {}
};
class Point : public _tagPOINT
{
public:
Point() :_tagPOINT(0, 0) {}
Point(int a, int b) :_tagPOINT(a, b) {}
Point(const Point & p) : _tagPOINT(p.x, p.y) {}
Point & operator=(const Point & rhs)
{ x = rhs.x; y = rhs.y; return *this; }
};
} // namespace OldCode
namespace NewCode
{
// Here is the new templated form of the above, complete
// with the error I do not understand.
// The error is in Point::operator=
template<class T>
struct _tagPOINT
{
T x;
T y;
_tagPOINT(T a, T b) :x(a), y(b) {}
};
template<class T>
class Point : public _tagPOINT<T>
{
public:
Point() :_tagPOINT<T>(0, 0) {}
Point(T a, T b) :_tagPOINT<T>(a, b) {}
Point(const Point & p) : _tagPOINT<T>(p.x, p.y) {}
Point & operator=(const Point & rhs)
{
//****** What's going on here?
x = rhs.x; // Shouldn't this line work?
// The compiler complains 'x': identifier not found.
// It works in the non-templated OldCode
//******
this->x = rhs.x; // This line compiles but I
// assumed this should be equivalent to the above
_tagPOINT<T>::x = rhs.x; // compiles: Direct reference
// to 'x' in tagPOINT
this->y = rhs.y;
return *this;
}
};
} // namespace NewCode
int main()
{
OldCode::Point OldPoint;
// Try all 3 template constructors
NewCode::Point<int> p1;
NewCode::Point<int> p2(0,0);
NewCode::Point<int> p3(p1);
p1 = p2;
}
|
PS: I hope this displays properly. For some reason the preview feature doesn't work for me in Microsoft Edge or Chrome. I'm not having any luck :(