Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Strange pimpl problem - const correctness not respected by compiler

3 views
Skip to first unread message

Daniel Lidström

unread,
Oct 14, 2008, 10:47:29 AM10/14/08
to
(I accidentally posted a first version to m.p.dotnet.languages.vc)

Hello!

I have a strange problem with my pimpl implementation. What happens is that
const correctness is not respected by the compiler. Among two methods, one
const and one non-const, the non-const version ends up being called on a
const
object. 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 Lidström

Igor Tandetnik

unread,
Oct 14, 2008, 12:27:35 PM10/14/08
to
"Daniel Lidström" <som...@microsoft.com> wrote in message
news:e80rJvg...@TK2MSFTNGP06.phx.gbl

> I have a strange problem with my pimpl implementation. What happens
> is that const correctness is not respected by the compiler. Among two
> methods, one const and one non-const, the non-const version ends up
> being called on a const
> object. Let me go straight to the code:
>
> class LineData
> {
> class LineDataImpl;
> LineDataImpl& mImpl;
>
> const Geometry& LineData::GetGeometry() const
> {
> return mImpl.GetGeometry();

const is shallow. mImpl is const, but LineDataImpl object it refers to
is not.

The difference would be easier to see if mImpl were declared as
LineDataImpl*. Then if LineData object is const, its mImpl member would
be LineDataImpl* const - but not const LineDataImpl*. That is, the
pointer itself can't change (say, to point to a different object), but
the object it points to happily can.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Doug Harrison [MVP]

unread,
Oct 14, 2008, 2:03:44 PM10/14/08
to
On Tue, 14 Oct 2008 12:27:35 -0400, "Igor Tandetnik" <itand...@mvps.org>
wrote:

>"Daniel Lidström" <som...@microsoft.com> wrote in message
>news:e80rJvg...@TK2MSFTNGP06.phx.gbl
>> I have a strange problem with my pimpl implementation. What happens
>> is that const correctness is not respected by the compiler. Among two
>> methods, one const and one non-const, the non-const version ends up
>> being called on a const
>> object. Let me go straight to the code:
>>
>> class LineData
>> {
>> class LineDataImpl;
>> LineDataImpl& mImpl;
>>
>> const Geometry& LineData::GetGeometry() const
>> {
>> return mImpl.GetGeometry();
>
>const is shallow. mImpl is const, but LineDataImpl object it refers to
>is not.
>
>The difference would be easier to see if mImpl were declared as
>LineDataImpl*. Then if LineData object is const, its mImpl member would
>be LineDataImpl* const - but not const LineDataImpl*. That is, the
>pointer itself can't change (say, to point to a different object), but
>the object it points to happily can.

Yes, we mean different things by "const reference" and "const pointer", and
the fact that this case reflects the "const pointer" concept is arguably a
bug in the language. That is, there is no such thing as "X& const x_ref",
but that's effectively what we have here. The const does not apply to the
referent, and the notion that the reference is an alias for the object
kinda falls apart here. This is in contrast to sizeof, which acknowledges
the meaninglessness of taking the size of a reference, which is not an
object, and applies it to the referent instead, which is an object.

--
Doug Harrison
Visual C++ MVP

Daniel Lidström

unread,
Oct 15, 2008, 2:57:13 AM10/15/08
to
"Doug Harrison [MVP]" <d...@mvps.org> wrote

> Yes, we mean different things by "const reference" and "const pointer",
> and
> the fact that this case reflects the "const pointer" concept is arguably a
> bug in the language. That is, there is no such thing as "X& const x_ref",
> but that's effectively what we have here. The const does not apply to the
> referent, and the notion that the reference is an alias for the object
> kinda falls apart here. This is in contrast to sizeof, which acknowledges
> the meaninglessness of taking the size of a reference, which is not an
> object, and applies it to the referent instead, which is an object.

Thanks for explaining the problem, Igor and Doug.

--
Daniel

Ben Voigt [C++ MVP]

unread,
Oct 15, 2008, 1:48:54 PM10/15/08
to

I think the solution would be:

const Geometry& LineData::GetGeometry() const
{

const LineDataImpl& cmImpl = mImpl;
return cmImpl.GetGeometry();
}


0 new messages