Re: Overloaded function lookup with const/volatile
On Aug 19, 10:06 pm, Marcel M=FCller <news.5.ma...@spamgourmet.org>
wrote:
James Kanze wrote:
It turned out that gcc compiles the code as expected. And
furthermore gcc also compiles it when I remove the methods
that take non-const references. Now I am really surprised.
Obviously gcc prefers the conversion to const X& over const
volatile X& for some reason.
Maybe because the standard requires it? From =A713.3.3.2/3:
Two implicit conversion sequences of the same form are
indistinguishable conversion sequences unless one of the
following rules apply:
-- Standard conversion sequence S1 is a better
conversion sequence than standard conversion
sequence S2 if
[...]
-- S1 and S2 are reference bindings (8.5.3), and
the types to which the references refer are the
same type except for top-level cv-qualifiers,
and the type to which the reference initialized
by S2 refers is more cv-qualified than the type
to which the reference initialized by S1 refers.
[...]
In the end, this is the same rule which causes the compiler to
prefer f( int& ) over f( int const& ) in cases where both can be
called.
Ah, good to know. I always thought that there are only two
levels with cv-qualifiers: with conversion and without
conversion. So in fact there are three.
There aren't levels. There's a partial ordering:
nothing < const
nothing < volatile
nothing < const volatile
const < const volatile
volatile < const volatile
And since the ordering is only partial, you can get ambiguities,
e.g.:
void f( Type const& obj ) ;
void f( Type volatile& obj ) ;
void g()
{
Type obj ;
f( obj ) ;
}
Both functions are callable, and there's no ordering between
them.
[...]
Volatile is used to mark shared pointer instances that may
change asynchronously. All access to these instances has to be
done logically atomic. The latter is achieved by invoking
different functions for volatile objects.
Volatile doesn't have any relationship with atomic. Depending
on the machine (and possibly alignment), the access to a given
type will be atomic or not, irrespective of the volatile.
At least under Unix and Windows (although Microsoft has
indicated that this will change under Windows), volatile has no
relations with threading, either. At least, the implementation
of volatile in Sun CC, g++ and VC++ doesn't do anything to
ensure that other threads "see" the modification, or even that
successive accesses to the same volatile variable are ordered
in main memory.
Similar here.
But since I do not access the volatile vars through C++ at
all, it makes no difference anyway. The compiler has only to
take the address of the volatile objects, which is obviously
invariant. Access is done by small assembler code fragments
only. OK, maybe I abused the qualifier.
Or maybe it's not needed at all:-). It's obviously irrelevant
to the assembler code fragments.
The alternative to using volatile here has significant
drawbacks too.
Whatever the drawbacks of other methods, the solution using
volatile doesn't work. Which is IMHO a killer drawback.
Why should it not work?
Because the compiler vendors don't specify it to work.
So far the multi-threaded test cases work pretty well.
If you're using "small assembler fragments" which do the right
thing, there's no reason why it shouldn't. But in that case,
the volatile almost doesn't change anything.
Of course, you could be using it for its impact on the overload
resolution, so that you get a different function---one which
uses the assembler snippets---if the variable is volatile. In
which case, the use is valid. But I'd certainly put in a
comment somewhere explaining this, because it's not the first
thing one thinks of when one sees volatile.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34