0

(I believe) I know about overloading functions based on const-ness: if the instant is const, the const method is called, otherwise the non-const one.

Example (also at ideone):

#include <iostream>

struct S
{
  void print() const { std::cout << "const method" <<std::endl };
  void print()       { std::cout << "non-const method" <<std::endl };
};

int main()
{
  S const s1;
  s1.print(); // prints "const method"
  S s2;
  s2.print(); // prints "non-const method"
  return 0;
};

I try/tried to make use of that in my code, but ran into some issues when the const overloaded methods don't have the same access category. It might be bad style, but here is an example that reflects the idea of returning references to avoid copying and using const to limit unintended alterations:

struct Color;
struct Shape
{
  double area;
};

class Geometry
{
public:
  // everybody can alter the color of the geometry, so 
  // they get a mutable reference
  Color& color() { return m_color; };

  // not everybody can alter the shape of the Geometry, so
  // they get a constant reference to the shape.
  Shape const& shape() const { return m_shape; };

protected:
  // derived classes can alter the shape, so they get 
  // access to the mutable reference to alter the shape.
  Shape & shape() { return m_shape; };

private:
  Shape m_shape;
  Color m_color;
};

The problem I am facing now is that I want the compiler to pick up the public, const-returning shape function if some other function messes with the Geometries, say color them by their area, for which this would need to access the shape of the Geometry:

// this one fails
void colorByArea() {
  for( Geometry g : geometryList )
  { g.color() = colorMap[g.shape().area]; }
}

// this one is a clunky workaround
void colorByArea() {
  for( Geometry g : geometryList )
  { 
    Geometry const& g_const = g;
    g.color() = colorMap[g_const.shape().area];
  }
}

This (or something similar) fails with the following fairly understandable error:

‘Shape& Geometry::shape()’ is protected 
  Shape & shape() { return m_shape; };

^ error: within this context
  g.color() = colorMap[g.shape().area];

(I put up a slightly simplified non-compiling example at ideone.)

I get (to a degree) why this is happeding:g is not const and hence the non-const shape(), which is protectec, is supposedly to be called -- but that obviously fails.

So I guess my QUESTION is: Is there a way to get some sort of "fall back" to a const-function if a non-const function is not accessible?

hcc23
  • 1,180
  • 11
  • 17
  • Do you mean, calling a `const` method on a non `const` object? – imreal Feb 27 '14 at 17:49
  • @Nick: Well, kinda-sorta: If there is a way to explicitly call a const version of a method over a (identically named) non-const version, then yes. – hcc23 Feb 27 '14 at 17:57
  • Not non-explicitly, you could use `const_cast`, but it is probably not what you want. – imreal Feb 27 '14 at 18:02

2 Answers2

1

Is there a way to get some sort of "fall back" to a const-function if a non-const function is not accessible?

No; overload resolution occurs before access check.

This is not just bad style; it is bad design. A public getter function is conceptually different from a protected function that lets code with knowledge of internals modify the object's internal state. In general the two functions need not even have related return types. Therefore they should not have the same name.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Sometimes I wonder why/what I googled before typing up a SO question... :/ http://compgroups.net/comp.lang.c++.moderated/overload-resolution-before-access-che/370761 Thanks for giving me a new starting point for some more learning. :) – hcc23 Feb 27 '14 at 18:10
0

You may use const_cast to allow to call the const version as:

int main()
{
  S s2;
  const_cast<const S&>(s2).print(); // prints "const method"
  return 0;
};

But it would be better/simpler to rename one of the method.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Thanks for reminding me that I can use `const_cast` to add const... Normally I just use it the other way round... – hcc23 Mar 03 '14 at 14:33