Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV gets aways with assigning to a const reference?

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

  1. anyone who writes code like that should have their hands cut off
  2. in the openCV source above, there is no redefinition of 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?

like image 638
suszterpatt Avatar asked Dec 01 '10 20:12

suszterpatt


2 Answers

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.

like image 166
aschepler Avatar answered Nov 03 '22 02:11

aschepler


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.

like image 28
wolfgang Avatar answered Nov 03 '22 00:11

wolfgang