Oppinion on 'least priviledge', 'const correctness', etc.

L

Lew

Öö Tiib said:
Seems that "Favor Immutability" is not that popular idiom. Google for

It's one of the most fundamental idioms in Java.
"Const Correctness" 39,000 results, "Favor Immutability" 1,080. It is

That's a measure of how often a particular phrase turns up, not how often the
topic comes up. Your "research' is a complete red herring.
more about how to create immutable classes, while in C++ you do not
need to (but may) make special classes for constant instances.

Yeesh. "How to create immutable classes" *is* a discussion of "favor
immutability". How come you didn't include those stats in your count? Hm?

The keywords differ in how they're applied.

Maybe Java doesn't use a fancy term; when discussing immutability and final we
just say, "making things final" or "making things immutable" or other phrases
with the word "final" and "immutable", and everyone understands that we talk
about that because of the advice to "favor immutability" without having to
quote that particular chapter title.

No one lasts long in Java without hearing about Joshua Bloch's /Effective
Java/, whence came the phrase "favor immutability", and no one progresses far
as a Java programmer without studying that book.

So strengthen your google-fu and try again, and don't quote misleading and
irrelevant statistics.

Öö Tiib said:
Huh? But these are tools, language features. Not mandatory to use
always but most like them since these really help. Perhaps that
'final' is simply considered enough by authors of java [sic]. There are fine
languages like Python with even less features supporting
immutability.

As we've established elsethread, 'final' and 'const' are somewhat similar in
certain respects, but not the same really. They fill a niche of immutability
in different languages with different ecologies, and do so at somewhat
different levels.

I stand corrected (thanks, Pete) on any implication that the keywords are
highly similar. I never intended to imply that. All I'm saying is that they
have a similarity in purpose, to render elements immutable.

Öö Tiib said:
Ok. Making primitive immutable with 'final' is yes in certain ways
same. It is mostly perhaps used for naming single constant values, not
write protection? You can also make a pointer immutable with 'final'.
That is sometimes done in C++ too but usually one uses a reference for
it ('const' is not needed at all).

Java doesn't have C++ references; what Java calls "reference" is actually a
pointer.
There similarities end. 'final' about member function means that it
can not be further overridden and 'final' about class means that it
can not be derived from. These are entirely different purposes than

I was only referring to the use of 'final' for variables. Method and class
names already cannot be changed to point to something different.
'const' has. It feels like 'final' is for some sort of global and meta-
immutability when 'const' is more for selectively write-protecting
(possibly mutable) data.

'final' serves that purpose in Java.
Everyone here seems to think that Java 'final' is just nothing a-'tall like
C[++] 'const'. They are, of course, mistaken.

Öö Tiib said:
'const' yes, feels more oriented for not giving (and taking) unneeded
privileges locally. Major feature of 'const' is to declare that code
will not modify the object pointed to by a pointer through that
pointer. Other feature is to declare that function does not modify its
parameter and third is to show that member function does not modify
the object. How you do any of these with 'final'?

Java cannot access an object by a pointer to a pointer, since those don't even
exist, so that purpose isn't needed. 'final' applied to a function parameter
has a cognate purpose - the function cannot change the contents of the
parameter. To prevent anything (not just a member function) from modifying
the object, Java uses 'final', but on the attributes of the object, not the
method.

Öö Tiib said:
I am not saying that different feature set makes one language better

Nor am I.
than other, just that 'final's purpose feels different and such

The purpose is similar, it's the mechanics that differ.
comparison feels stretched out, nothing to do. You can have immutable
view of mutable data by writing special interface in java [sic], but the

Java interfaces cannot enforce immutability.
cost is higher than with 'const' and what it all has to do with
'final'?

Immutability in Java is enforced with 'final', as immutability in C++ is with
'const'. Yes, there are differences, of course. They aren't the same. But
given the different ecologies, they have a (sort of) similar purpose. That's
what.
 
J

Jonathan Lee

Maybe Java doesn't use a fancy term; when discussing immutability and final we
just say, "making things final" or "making things immutable" or other phrases
with the word "final" and "immutable", and everyone understands that we talk
about that because of the advice to "favor immutability" without having to
quote that particular chapter title.

This clarifies (for me) a great deal about your earlier posts. Thanks.

--Jonathan
 
J

Jim Janney

Jonathan Lee said:
Therefore it doesn't exist?

Er.. no. In fact, I even went out of my way to say that I wasn't
experienced in Java so people wouldn't draw that conclusion.
 Anyway, the claim isn't that there's an exact equivalent to
"const correctness" but that Java's 'final' has similarities to
C++'s 'const', and relative to the Java language fills the same
ecological niche.

The OP was asking about const correctness, not the const keyword.
As for the "final" and "const" keywords being similar... that's
interesting, but a distinct topic.
Everyone here seems to think that Java 'final' is just nothing a-'tall like
C[++] 'const'.  They are, of course, mistaken.

We don't think that.

I think that, and I've used both C++ and Java for years. Final is a
very limited substitute for const. So is immutability, for that
matter. The closest thing Java can offer is something like
Collections.unmodifiableCollection(), and the language provides no way
for the compiler to enforce that, so it depends on runtime checking.
 
J

Jim Janney

Daniel said:
Neither Java or C++ has any way of marking a function as "pure".

C++ methods can be declared as const, indicating that they don't
change the state of the objects they are invoked on. There's no
equivalent for this in Java. You might conceivably use an annotation,
but the compiler wouldn't enforce it.
 
J

Jim Janney

Jim Janney said:
Jonathan Lee said:
Jonathan Lee wrote:
I've never heard of an equivalent of "const correctness" in Java,
Therefore it doesn't exist?

Er.. no. In fact, I even went out of my way to say that I wasn't
experienced in Java so people wouldn't draw that conclusion.
 Anyway, the claim isn't that there's an exact equivalent to
"const correctness" but that Java's 'final' has similarities to
C++'s 'const', and relative to the Java language fills the same
ecological niche.

The OP was asking about const correctness, not the const keyword.
As for the "final" and "const" keywords being similar... that's
interesting, but a distinct topic.
Everyone here seems to think that Java 'final' is just nothing a-'tall like
C[++] 'const'.  They are, of course, mistaken.

We don't think that.

I think that, and I've used both C++ and Java for years. Final is a
very limited substitute for const. So is immutability, for that
matter. The closest thing Java can offer is something like
Collections.unmodifiableCollection(), and the language provides no way
for the compiler to enforce that, so it depends on runtime checking.

I think part of the confusion here is that C++ overloads all its key
words*, so const actually does a number of very different things, only
some of which can be mimicked with final. Rather than saying "Java
doesn't need const correctness, because it has final and immutable
classes", I would say "Java doesn't have statically checked const
correctness, just as it doesn't have multiple inheritance, and for the
most part no one has missed it."

Const correctness is a nuisance because it requires transitive
closure, so that making a single change can ripple through a lot of
other code. And it's confusing, which is why there's so much
discussion on it. Personally, I like it, but I can understand why
some people think it's more trouble than it's worth.

* And if you think const is bad, take a look at static.
 
D

Daniel

..>
C++ methods can be declared as const, indicating that they don't
change the state of the objects they are invoked on.  .

On the contrary, there are no guarantees that they don't change the
state of the object, for any meaningful definition of state. There
are only restrictions on the first level of data in the object, there
are no restrictions on changing the values of embedded variables, or
data addressed by a pointer.

-- Daniel
 
D

Daniel

  I fail to see how what you wrote invalidates what I wrote.
I interpreted "change the object" to mean "change the state of the
object", and there is no guarantee that const versions of methods
don't do that, for any meaningful definition of "state". The term
const is so overloaded that it's possible we're talking about
different things.

Best regards,
Daniel
 
Ö

Öö Tiib

On the contrary, there are no guarantees that they don't change the
state of the object, for any meaningful definition of state.  There
are only restrictions on the first level of data in the object, there
are no restrictions on changing the values of embedded variables, or
data addressed by a pointer.

C++ gives no strong guarantees about anything. Notice that Jonathan
said 'indicates' not 'guarantees'. It is matter of people who use it
to decide what is evil and what is fine. Widespread concept is that
method declared const modifying objects state is evil way to mislead
users of the interface and only very few things are more evil than
lying to your comrades.

Lets look why compiler does not enforce it? Well, there are components
of object (part of objects state) and there are other objects related
by other sense (not part of objects state). Language does not make
strong difference at what a pointer member of class points, is it a
component, is it otherwise related object or maybe pointed at object
is itself abstraction of some sort of relation. Teams policy may make
difference, for example by using boost::scoped_ptr<> (or direct data
member) for a component and boost::weak_ptr<> (or reference, or raw
pointer) for other, non-owning relations.

Compiler does know nothing about such policies. Entity that should
decide and make difference and give guarantees is between chair and
keyboard. Compiler lets to modify all pointed at by members objects,
since it assumes that such entity knows exactly what it does. How
should compiler give guarantees that such entity has ability to think?
Compiler can not think, it is well-known fact.

C++1x will introduce more ways to add more detailed attributes to
things. It feels like for some that adds even more stuff to
circumvent, misuse and then complain about lack of strong guarantees.
 
J

Jim Janney

Daniel said:
On the contrary, there are no guarantees that they don't change the
state of the object, for any meaningful definition of state. There
are only restrictions on the first level of data in the object, there
are no restrictions on changing the values of embedded variables, or
data addressed by a pointer.

The const declaration is part of the method's contract. It's the
programmer's responsibility to see that the method fulfills that
contract, yes: I wouldn't have it any other way. As with most
contracts, the primary benefit is to the method's callers.
 
D

Daniel

Notice that Jonathan said 'indicates' not 'guarantees'.
It is matter of people who use it to decide what is
evil and what is fine. Widespread concept is that
method declared const modifying objects state is evil way
to mislead users of the interface

The compiler, though, can only rely on what the language specifies,
and the language does not specify that a const method cannot change
the object's state. The compiler cannot rely on conventions, and
cannot take advantage of them to produce more efficient code.

-- Daniel
 
D

Daniel

The const declaration is part of the method's
contract.  It's the programmer's responsibility to see
that the method fulfills that contract
But what exactly is the contract?

The meaning of const is what the C++ standard says it is.

-- Daniel
 
F

Francesco S. Carta

The compiler, though, can only rely on what the language specifies,
and the language does not specify that a const method cannot change
the object's state.

The above statement seems partly wrong to me: up to a some degree, the
compiler can enforce the C++ specification, and in this case, it
specifies that a const method cannot change the members of the object it
is called upon (unless they're declared "mutable") - in practice,
though, this means that the compiler does its best to forbid that method
to /directly/ change those members, so yes, the compiler cannot fully
enforce the directive, but that does not mean that such a directive does
not exist: obviously, the compiler control can be circumvented, but that
would be a deliberate choice of the programmer, for which the programmer
takes on all responsibilities.
The compiler cannot rely on conventions, and
cannot take advantage of them to produce more efficient code.

But it can rely on the code it analyses. In all the cases where a
compiler is able to prove its "right" to do some optimization, it will
do it - if properly instructed to do so, eventually.

For example, even if some variable is not declared as "const", if the
analysis can prove that no instruction changes that variable during some
particular lapse of time, then the compiler is free to cache its value
for performance reasons.

All the features, keywords and checks are there only for the human
advantage and protection, the computer does not care if the code it runs
is safe or clever - it can perfectly run as hell on the abyss' edge
without falling, as long as its code "works".

Making that code "to work" is the human task, and additionally, humans
create conventions to "stay on the path" and they instruct compilers to
"recall to the human to stay on the path".

At least, all the above is what I have understood about these subjects
so far, though, I'm not an implementer nor a C++ standard expert, so you
might take my words with a grain of salt.
 
Ö

Öö Tiib

The compiler, though, can only rely on what the language specifies,
and the language does not specify that a const method cannot change
the object's state.  The compiler cannot rely on conventions, and
cannot take advantage of them to produce more efficient code.

const member function can not modify any data members of object but
the ones marked explicitily as always 'mutable' (such are rare), nor
can it call other non-const member functions of it nor can it call the
non-const member functions of its data members.

Compiler can take advantage even of unmodified mutable things staying
immutable in the frame where compiler wants to optimize something. Do
not underestimate compiler writers. These are clever guys. 'const' is
there for to help programmers and optimizations are lesser concern.

Protection can be circumvented by const_cast. One using it has likely
to prove to his comrades that it was least evil thing in situation he
was in to do. That will be hard to prove to better of peers since C++
is extremely flexible.

That leaves only state pointed at by raw pointer members in class that
stay mutable. I already told why it is so, such raw pointer may point
at something that is not part of the state of class. OTOH i have also
seen policies that declare raw pointers as 'not C++' and forbid usage
of raw pointers. Smart pointers however may keep and enforce constness
as transitive depending on type of relation whose abstraction they
are.
 
S

Stuart Redmann

const member function can not modify any data members of object but
the ones marked explicitily as always 'mutable' (such are rare), nor
can it call other non-const member functions of it nor can it call the
non-const member functions of its data members.

Compiler can take advantage even of unmodified mutable things staying
immutable in the frame where compiler wants to optimize something. Do
not underestimate compiler writers. These are clever guys. 'const' is
there for to help programmers and optimizations are lesser concern.

Right. Making objects const does not mean that the compiler is allowed
to cache the returned value of member functions, neither in C++ nor in
Java. Most compilers will optimize away const variables whose value is
known at compile time (so that we can replace #defines by const
variables), btu that is only a very weak optimization. Any caching of
method calls must be provided by the programmer.
Protection can be circumvented by const_cast. One using it has likely
to prove to his comrades that it was least evil thing in situation he
was in to do. That will be hard to prove to better of peers since C++
is extremely flexible.

That leaves only state pointed at by raw pointer members in class that
stay mutable. I already told why it is so, such raw pointer may point
at something that is not part of the state of class. OTOH i have also
seen policies that declare raw pointers as 'not C++' and forbid usage
of raw pointers. Smart pointers however may keep and enforce constness
as transitive depending on type of relation whose abstraction they
are.

C++ offers the means to extend the const correctness even over
pointers:

class SomeClass
{
public:
void foo () const {}
void bar () {}
};

class AnotherClass
{
protected:
SomeClass* SomeObject;
public:
AnotherClass (SomeClass* Object)
: SomeObject (Object)
{}
SomeClass* GetObject ()
{
return SomeObject;
}
const SomeClass* GetObject () const
{
return SomeObject;
}
};

int main ()
{
SomeClass a;
const AnotherClass b (&a);
b.GetObject ()->foo (); // OK
b.GetObject ()->bar (); // Compilation error: b is const

AnotherClass c (&a);
c.GetObject ()->foo (); // OK
c.GetObject ()->bar (); // OK: c is not const
}

Stroustrup mentiones this technique in his book (can't cite the page
since I seem to haave mislaid it). Although it's a pain in the neck to
write const-overloaded accessors for member pointers, this is a
technique that can extend const-correctness so that it works for
everything.

Regards,
Stuart
 
J

Jorgen Grahn

["Followup-To:" header set to comp.lang.c++ -- again.]

I have successfully avoided using C++ to any significant extent for
nearly a decade. In the 90's, it came up on a regular enough basis to
dissuade me from making more than a half-hearted attempt to "const"-ify
my code.

Maybe it's not as big of a problem as it used to be.

Lots have happened since the 1990s. Quality APIs (C and C++) use const today.
(At least on Unix, where I do my work.)

/Jorgen
 
J

Jorgen Grahn

I interpreted "change the object" to mean "change the state of the
object", and there is no guarantee that const versions of methods
don't do that, for any meaningful definition of "state". The term
const is so overloaded that it's possible we're talking about
different things.

He said "the const version of the member function"; I see no ambiguity
there. But I don't quite understand the rest of his reasoning.
Especially in the presence of aliasing.

I used to expect bit efficiency gains from const. I don't expect that
much nowadays, but I don't care: the other benefits of const justify it
perfectly well.

/Jorgen
 
J

Juha Nieminen

Jorgen Grahn said:
But I don't quite understand the rest of his reasoning.

What is so unclear about it?

Which is more efficient, this:

const char& operator[](unsigned index) const
{
return str[index];
}

or this:

char& operator[](unsigned index)
{
deep_copy_if_needed();
return str[index];
}

?

That's how a class using copy-on-write would need to be implemented.
 
Ö

Öö Tiib

Right. Making objects const does not mean that the compiler is allowed
to cache the returned value of member functions, neither in C++ nor in
Java. Most compilers will optimize away const variables whose value is
known at compile time (so that we can replace #defines by const
variables), btu that is only a very weak optimization. Any caching of
method calls must be provided by the programmer.



C++ offers the means to extend the const correctness even over
pointers:

class SomeClass
{
public:
  void foo () const {}
  void bar () {}

};

class AnotherClass
{
protected:
  SomeClass* SomeObject;
public:
  AnotherClass (SomeClass* Object)
    : SomeObject (Object)
  {}
  SomeClass* GetObject ()
  {
    return SomeObject;
  }
  const SomeClass* GetObject () const
  {
    return SomeObject;
  }

};

int main ()
{
  SomeClass a;
  const AnotherClass b (&a);
  b.GetObject ()->foo ();  // OK
  b.GetObject ()->bar ();  // Compilation error: b is const

  AnotherClass c (&a);
  c.GetObject ()->foo ();  // OK
  c.GetObject ()->bar ();  // OK: c is not const

}

Stroustrup mentiones this technique in his book (can't cite the page
since I seem to haave mislaid it). Although it's a pain in the neck to
write const-overloaded accessors for member pointers, this is a
technique that can extend const-correctness so that it works for
everything.

Yes, this is obvious. Only problem of it is that *SomeObject is not
const within implementation of some const member of AnotherClass and
so may be modified by mistake there. Special smart pointer that
extends constness by its nature removes that issue as well.
 
S

Stuart Redmann

Yes, this is obvious. Only problem of it is that *SomeObject is not
const within implementation of some const member of AnotherClass and
so may be modified by mistake there. Special smart pointer that
extends constness by its nature removes that issue as well.

I see what you mean. I think the following template class should
achieve this:

// Wrapper for plain pointers that behaves as const-correct
// accessor.
template<class t_Class>
class ConstCorrectAccessor
{
t_Class* m_InternalPointer;
public:
ConstCorrectAccessor (t_Class* Pointer)
: m_InternalPointer (Pointer)
{}

// Accessor methods with const-correct overload.
const t_Class* operator-> () const {return m_InternalPointer;}
t_Class* operator ->() {return m_InternalPointer;}
};

class SomeClass
{
public:
void foo () const {}
void bar () {}
};

class AnotherClass
{
public:
ConstCorrectAccessor<SomeClass> SomeObject;
public:
AnotherClass (SomeClass* Object)
: SomeObject (Object)
{}

void foo () const
{
SomeObject->foo (); // OK
SomeObject->bar (); // Error: Non-const method on SomeObject.
}
};

int main ()
{
SomeClass a;
const AnotherClass b (&a);
b.SomeObject->foo (); // OK
b.SomeObject->bar (); // Compilation error: b is const

AnotherClass c (&a);
c.SomeObject->foo (); // OK
c.SomeObject->bar (); // OK: c is not const
}


Do you know whether such a thing is part of the STL/boost?

Regards,
Stuart
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,186
Latest member
vinaykumar_nevatia

Latest Threads

Top