Question

(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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top