Strange pimpl problem - const correctness not respected

  • Thread starter Thread starter Daniel Lidström
  • Start date Start date
D

Daniel Lidström

Hello!

I have a strange problem with my pimpl implementation. What happens is that
const correctness is not respected. Let me go straight to the code:

#include <iostream>

struct Geometry {};

class LineData
{
class LineDataImpl;
LineDataImpl& mImpl;

public:

LineData();

const Geometry& GetGeometry() const;
/* */ Geometry& GetGeometry() /* */;
};

class LineData::LineDataImpl
{
Geometry mGeometry;

public:

const Geometry& GetGeometry() const
{
std::cout << "Calling const overload" << std::endl;
return mGeometry;
}

Geometry& GetGeometry()
{
std::cout << "Calling non-const overload" << std::endl;
return mGeometry;
}
};

LineData::LineData()
: mImpl(*(new LineDataImpl))
{ }

const Geometry& LineData::GetGeometry() const
{
return mImpl.GetGeometry();
}

Geometry& LineData::GetGeometry()
{
return mImpl.GetGeometry();
}

int main()
{
const LineData lineData;
const Geometry& geometry = lineData.GetGeometry();

return 0;
}

This sample shows that despite my intentions of being const correct, the
compiler ends up calling the non-const overload. What is going on here?
I'm using Visual Studio 2008, SP1.

Thanks in advance!
 
Daniel said:
Hello!

I have a strange problem with my pimpl implementation. What happens is
that const correctness is not respected. Let me go straight to the code:

[snip]

class LineData
{
class LineDataImpl;
LineDataImpl& mImpl;

That's because your mImpl is not const.
[snip]
const Geometry& LineData::GetGeometry() const
{
return mImpl.GetGeometry();

Change this to:
return static_cast<const LineDataImpl&>(mImpl).GetGeometry();

Tom
 
Daniel said:
LineData::LineData()
: mImpl(*(new LineDataImpl))
{ }

Also note that this new leaks. I assume this is a test only, but your
real code should arrangements to delete this pointer.

Tom
 
Tamas Demjen said:
Also note that this new leaks. I assume this is a test only, but your real
code should arrangements to delete this pointer.

Yes, the real code does delete the pointer :-)
Thanks for the workaround Tamas!
 
Back
Top