/*Orion Lawlor's Simple C++ Examples, olawlor@acm.org
Shows the semantics of all the flavors of "const" types.
*/ 
/*
The "const" keyword in modern C and C++ tells the compiler
"I'm not allowed to modify this".  Any attempt to assign to
or otherwise change a "const" value results in a compile-time
error.  This is useful, as it documents and enforces the programmer's
intentions.

That said, there are quite a few places the "const" keyword can be
used; these places can result in:
  1.) Compile errors like "parse error before `const'".
  2.) Unintentionally allowing more or fewer changes than you wanted.
  3.) Allowing exactly the changes you want.
Because 1 and 2 are so common, some programmers avoid "const" completely.

The first confusing aspect of "const" is that it can equivalently
go before *or* after a value type: "const int x" and "int const x"
are completely interchangeable.  "const int" is a bit more common,
but "int const" makes a bit more sense.

"const" is most confusing when used with pointers. Like other hairy
types, these only make sense when read from inside to outside
(right to left).
*/

int main() 
{
/* value type: just a regular int */
	int i=1;
	
	
/* reference to value: can do anything to value (but can't change reference) */
	int &ri=i;
	i+=ri; /* reads are OK */
	ri++; /* modification is OK */
	
/* reference to const value: can only read, not write. */
	int const &rci=i; 
	const int &ric=rci; /* an equivalent form */
	
	i+=rci; /* reads OK */
	// rci++;  // Error: increment of read-only reference `rci' 

/* const references, unlike const pointers, do not exist: */
	// int &const cri=i; // Error: `const' qualifiers cannot be applied to `int&'
	
	
/* pointer to value: can do anything to value or pointer */
	int *pi=&i;
	i+=*pi; /* reads are OK */
	(*pi)++; /* modify i */
	pi++; /* modify pointer */
	pi=&i; /* change pointer back */
	
/* pointer to const value: can't change value, but CAN change pointer */
	int const *pci=&i; 
	const int *pic=pci; /* an equivalent form */
	
	i+=*pci; /* reads are OK */
	// (*pci)++; // Error: increment of read-only location
	pci++; /* write to pointer */
	pci=pi; /* write from non-const pointer */
	
/* const pointer to value: can't change pointer, but CAN change value */
	int *const cpi=&i; 
	
	i+=*cpi; /* reads are OK */
	(*cpi)++; /* write to value */
	// cpi++; // Error: increment of read-only variable `cpi'
	
/* const pointer to const value: can't change value OR pointer */
	int const *const cpci=&i; 
	const int *const cpic=cpci; /* equivalent form */
	
	i+=*cpci;
	// (*cpci)++; // Error: increment of read-only location
	// cpci++; // Error: increment of read-only variable `cpci'
	
/* pointer to pointer to value: can change anything */
	int **ppi=&pi;
	i+=**ppi; /* read from value */
	(**ppi)++; /* write to value */
	(*ppi)++; /* write to pointer */
	ppi++; /* write to pointer pointer */
	
/* pointer to const pointer to value:  */
	int *const *pcpi=&cpi;
	(**pcpi)++; /* write to value */
	// (*pcpi)++; // Error: increment of read-only location
	pcpi++; /* write to pointer pointer */
	pcpi=&cpi; /* reset value */
	
/* final exam: */
	int *const * *const cppcpi=&pcpi;
	(***cppcpi)++; /* change value */
	// (**cppcpi)++; // Error: increment of read-only location
	(*cppcpi)++; /* change pcpi */
	// cppcpi++; // Error: increment of read-only variable `cppcpi'
}
/*<@>
<@> ******** Program output: ********
<@> */
