Objects reference const correctness

I was reading this article on const correctness because I think I should use it more often to save me from writing stupid things :smiley: So after reading it I started doing some tests.

First with a simple byte:

byte myVal = 6;

void setup() {
  Serial.begin(115200);
  printRef(myVal);
}

void loop() {
  
}

void printRef(const byte& in){
  //in = 7; //error: assignment of read-only reference 'in'
  Serial.print(in);
}

And indeed, as expected the assignment in printRef() fails.

So far so good! Okay, lets ++ this and try objects!

class Foo{
  public:
    Foo(byte val) :
      _val(val)
    {
      
    }
    
    byte _val;
};

Foo myFoo = 12;

void setup() {
  Serial.begin(115200);
  printRef(myFoo);
}

void loop() {
  
}

void printRef(const Foo& in){
  //in._val = 13; //error: assignment of member 'Foo::_val' in read-only object
  Serial.print(in._val);
}

Again, an error as expected :slight_smile:

But it's still just variable manipulation, no methods involved. Let's spice it up with non-const functions.

class Foo{
  public:
    Foo(byte val) :
      _val(val)
    {
      
    }

    void set(byte val){
      _val = val;
    }

    byte get() const{
      return _val;
    }
    
    byte _val;
};

Foo myFoo = 12;

void setup() {
  Serial.begin(115200);
  printRef(myFoo);
}

void loop() {
  
}

void printRef(const Foo& in){
  in.set(42); //I expected an error...
  Serial.print(in._val);
}

I expected this to give me an error... Because the set method isn't a const function. But it does not... No error and it prints 42...

I'm I expecting the wrong thing? Is Arduino messing with it?

I expected this to give me an error... Because the set method isn't a const function. But it does not... No error and it prints 42...

I don't see why you expected an error. The variable being assigned a value isn't const. The function does not promise to not change the value of what it was passed, and, even if it did, it does not change the input argument.

Turn on verbose compilation and it gives you a warning:

C:\Google Drive\Documents\Arduino\sketch_mar15a\sketch_mar15a.ino: In function 'void printRef(const Foo&)':

C:\Google Drive\Documents\Arduino\sketch_mar15a\sketch_mar15a.ino:32:12: warning: passing 'const Foo' as 'this' argument of 'void Foo::set(byte)' discards qualifiers [-fpermissive]

   in.set(42); //I expected an error...

            ^

What's that -fpermissive nonsense? It's a compiler option that Arduino enables.

-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will allow some nonconforming code to compile.

Your expectations are correct. This code should fail. It only compiles because Arduino turned on the compiler option to be more loose with the rules.

I adapted the code to try compiling it on an x86 C++ compiler that doesn’t have -fpermissive enabled. I got the exact same message, except this time it is a proper error that stops compilation and not just a warning.

#include <iostream>
#include <stdint.h>

typedef uint8_t byte;

class Foo{
  public:
    Foo(byte val) :
      _val(val)
    {
      
    }

    void set(byte val){
      _val = val;
    }

    byte get() const{
      return _val;
    }
    
    byte _val;
};

Foo myFoo = 12;

void printRef(const Foo& in){
  in.set(42); //I expected an error...
  cout << (in._val);
}

void setup() {
  printRef(myFoo);
}

void loop() {
  
}

int main(int argc, char** argv)
{
	setup();
	return 0;
}

And if your playing around with const, here's some fun for you: What is the difference between the following 3 pointer declarations:

  • const int *
  • int const *
  • int * const

For extra credit: int const * const

Thanks Jiggy-Ninja! That shows I’m not crazy :smiley: Sorry Paul…

But starting out with the easy part :stuck_out_tongue:
1 and 2 are the same, variable pointer to constant data
3 constant pointer to variable data
4 constant pointer to constant data :slight_smile:

But I must still be blind because I have verbose enabled (always) and I don’t see the warning…

And again, I’m glade I’m not crazy but it does suck a bit that the Arduino IDE has turned it off / turned it into a warning :confused: Would just be a great tool to use to prevent some stupid errors.

constCorrectConsoleNoError.txt (26.2 KB)

Set compiler warnings to All.

How could I've missed that :-[ I had it to the (assuming) default of none :-[ :-[ :-[

And this now indeed works as I thought it would except with a warning instead of an error :slight_smile: Thanks again!

1 and 2 are the same, variable pointer to constant data

Actually, they are not the same. One is correct and one is not really. The const keyword is supposed to follow the part that is to be const. So, int const is how to define an integer variable that is constant. (Isn't that an oxymoron?)

const int is supported, but it isn't really correct. I think it is only supported because int const looks so weird. Why the designers of C thought the keyword should modify the term to the left, instead of the right is a mystery to me.