I stumbled upon this piece of code in the openCV source ( cxoperations.hpp, line 1134, in the definition of the Vector
class ):
Vector(const Vector& d, const Range& r)
{
if( r == Range::all() )
r = Range(0, d.size());
// some more stuff...
}
Note that the Vector
class has no data member called r
(and indeed, the identifier r
only occurs in one more place in the entire class definition, as a parameter in another method). So apparently, that right there is an assignment to a const
reference.
I tried to reproduce a minimal example:
#include <iostream>
class Foo
{
public:
int _a;
Foo(int a) : _a(a) {}
};
int main()
{
Foo x(0);
const Foo& y = x;
printf("%d\n", y._a);
y = Foo(3);
printf("%d\n", y._a);
}
This, of course, fails to compile: g++ gives the error
test.cpp:15: error: passing `const Foo' as `this' argument of `Foo& Foo::operator=(const Foo&)' discards qualifiers
The only way I got it to work is by overriding operator=
like this:
#include <iostream>
class Foo
{
public:
int _a;
Foo(int a) : _a(a) {}
Foo& operator=(Foo rhs) const
{
Foo& tmp = const_cast<Foo&>(*this);
tmp._a = rhs._a;
return const_cast<Foo&>(*this);
}
};
int main()
{
Foo x(0);
const Foo& y = x;
printf("%d\n", y._a);
y = Foo(3);
printf("%d\n", y._a);
}
This compiles, and prints "0 3" as expected. The problem here is that
operator=
that takes Range
parameters (Range
-related functions are just above the definition of Vector
, starting at line 1033)Obviously I'm missing something, since the openCV source compiles. My question is, what is really going in in the r = Range(0, d.size());
line that makes it legal?
I notice cv's Vector
is a class template. So if that class method was never instantiated, there was no compiler error. My guess is that if you try
Vector<int> a;
Vector<int> b(a, Range::all());
you'll get a compiler error on that suspicious-looking line. Then you can report it as a bug in the OpenCV source.
My theory is that the offending code is never used and therefore never instantiated. Vector is a template, after all.
Consider this code:
template <class T>
class Vector
{
public:
Vector()
{
}
Vector(const Vector & x, const int & y)
{
y = 54;
}
};
// template class Vector<float>;
void foo()
{
Vector<float> v1;
// Vector<float> v2(v1, 42);
}
GCC (version 4.5.1) accepts this, but complains as soon as you add that call to the second constructor or the eplicit template instantiation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With