I've run into some *very* nasty trouble which I could (after hours of
work) trace to a problem in my use of the const keyword (which
appearently has not been appropriate). It is very difficult to trace, as
it only appears when the program is compiled with g++ and -O3 (-O2 and
below work fine).
So I'm guessing it's some kind of aliasing issue.
One of my classes provides an operator*=, which takes a const Fred& as a
parameter. As soon as I remove the const, it also works with -O3.
Now since it is very difficult to trace remotely, I have some general
questions about usage of const:
1. Is it always safe to do a c-style cast in which const is *added*?
I.e. I have a method which can access a foo* r/w - can it also return
(const foo*)x?
2. Is there a difference between const_cast and a c-style cast which
modifies only the const keyword?
3. In a class like this:
class foo {
private:
int *x;
public:
void blah() const {
x[9] = 123;
}
};
Is it safe to declare blah() const?
Kind regards,
Johannes
--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verlᅵsterung von Gott, Bibel und mir und bewusster Blasphemie."
-- Prophet und Visionᅵr Hans Joss aka HJP in de.sci.physik
<48d8bf1d$0$7510$5402...@news.sunrise.ch>
Reproduce in small program, post complete code.
> Now since it is very difficult to trace remotely, I have some general
> questions about usage of const:
>
> 1. Is it always safe to do a c-style cast in which const is *added*?
No, it's not always safe to add const.
See the FAQ.
And you should avoid C style casts.
> I.e. I have a method which can access a foo* r/w - can it also return
> (const foo*)x?
Sorry, that's a meaningless question: the two things are not related.
> 2. Is there a difference between const_cast and a c-style cast which
> modifies only the const keyword?
Yes.
You have no guarantee what the C style cast does.
And perhaps that's your problem, that you have introduced as reinterpret_cast
where you thought you were just adding const. Wouldn't surprise me. Remove all C
casts in your code.
> 3. In a class like this:
>
> class foo {
> private:
> int *x;
> public:
> void blah() const {
> x[9] = 123;
> }
> };
>
> Is it safe to declare blah() const?
That depends on whether 'x' points to per-instance data or not.
It's unclear since you have chosen to express the code at the lowest possible
level of abstraction (check out e.g. std::vector in your nearest textbook).
That in turn makes it impossible for the compiler to tell you whether you're
doing something invalid or not: by using raw pointers to raw arrays you have
told the compiler to shut up, as if you know what you're doing (which you admit
here you don't, so it's silly to tell the compiler that you do), and that's also
the case with C casts, which you should remove first of all, not a single left.
Cheers & hth.,
- Alf
> Hello group,
>
> I've run into some *very* nasty trouble which I could (after hours of
> work) trace to a problem in my use of the const keyword (which
> appearently has not been appropriate). It is very difficult to trace,
> as it only appears when the program is compiled with g++ and -O3 (-O2
> and below work fine).
>
> So I'm guessing it's some kind of aliasing issue.
>
> One of my classes provides an operator*=, which takes a const Fred& as
> a parameter. As soon as I remove the const, it also works with -O3.
>
> Now since it is very difficult to trace remotely, I have some general
> questions about usage of const:
See http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8
> 1. Is it always safe to do a c-style cast in which const is *added*?
> I.e. I have a method which can access a foo* r/w - can it also return
> (const foo*)x?
For adding a const you don't need a cast, this is an implicit
conversion.
> 2. Is there a difference between const_cast and a c-style cast which
> modifies only the const keyword?
Yes, the c-style cast can be screwed up much more easily! And the
results are ill-formed or unspecified if the c-style cast does not
correspond to some certain sequences of standard casts. Otherwise, it
should be the same though.
>
> 3. In a class like this:
>
> class foo {
> private:
> int *x;
> public:
> void blah() const {
> x[9] = 123;
> }
> };
>
> Is it safe to declare blah() const?
What you mean by 'safe'? This is valid C++, so I assume it should be
'safe'. Post some real code exhibiting he problem!
Paavo
>> 3. In a class like this:
>>
>> class foo {
>> private:
>> int *x;
>> public:
>> void blah() const {
>> x[9] = 123;
>> }
>> };
>>
>> Is it safe to declare blah() const?
>
> What you mean by 'safe'? This is valid C++
... apart from the obvious fact that x cannot be initialized to an array
containing at least 10 elements, so calling blah() will yield UB. Just
wanted to mention that before somebody else starts nitpicking...
Paavo
Since this is not possible I have chosen to just ask my questions in
order to find the problem myself. The code is around 20 kLOC total
containing at least 6 libraries which are dynamically loaded at runtime.
If I *could* reproduce the problem chances are I could also fix it.
>> Now since it is very difficult to trace remotely, I have some general
>> questions about usage of const:
>>
>> 1. Is it always safe to do a c-style cast in which const is *added*?
>
> No, it's not always safe to add const.
>
> See the FAQ.
I've read the FAQ section about const correctness (actually: in advance
to posting here) - I did not find this in there, though. I did not find
"const" methods in there either.
> And you should avoid C style casts.
What is the difference between a reinterpret_cast and a C-style cast?
>> I.e. I have a method which can access a foo* r/w - can it also return
>> (const foo*)x?
>
> Sorry, that's a meaningless question: the two things are not related.
Sigh.
>> 2. Is there a difference between const_cast and a c-style cast which
>> modifies only the const keyword?
>
> Yes.
>
> You have no guarantee what the C style cast does.
The C style cast yields UB?
> And perhaps that's your problem, that you have introduced as
> reinterpret_cast where you thought you were just adding const. Wouldn't
> surprise me. Remove all C casts in your code.
There were indeed a few instances where that was the case. I removed
them, the problem stayed.
>> 3. In a class like this:
>>
>> class foo {
>> private:
>> int *x;
>> public:
>> void blah() const {
>> x[9] = 123;
>> }
>> };
>>
>> Is it safe to declare blah() const?
>
> That depends on whether 'x' points to per-instance data or not.
Can you elaborate? Suppose there are two different scenarios:
class foo1 {
private:
int *x;
public:
foo() {
x = new int[128];
}
void blah() const {
x[9] = 123;
}
};
class foo2 {
private:
int *x;
public:
foo() {
x = singelton::get();
}
void blah() const {
x[9] = 123;
}
};
Never mind the lost memory in foo1 and suppose the static singleton::get
returns a pointer to global memory which will never change.
> It's unclear since you have chosen to express the code at the lowest
> possible level of abstraction
Yes, because that is where it becomes difficult. It's exactly constructs
as above that I want to know about, hence my question. This was
deliberately done so.
Regards,
> Yes, the c-style cast can be screwed up much more easily! And the
> results are ill-formed or unspecified if the c-style cast does not
> correspond to some certain sequences of standard casts. Otherwise, it
> should be the same though.
Can you elaborate? What do you mean by screwed up more easily? Can you
provide an example? Can you point me to the part of the standard where
this is discussed?
>> 3. In a class like this:
>>
>> class foo {
>> private:
>> int *x;
>> public:
>> void blah() const {
>> x[9] = 123;
>> }
>> };
>>
>> Is it safe to declare blah() const?
>
> What you mean by 'safe'? This is valid C++, so I assume it should be
> 'safe'. Post some real code exhibiting he problem!
By safe in this case I mean: Can the "const" keyword of the blah()
method introduce trouble when a compiler is doing certain kinds of
optimization? Appearently this depends on where x is poining to, so I
clearified my question in response to Alf.
Regards,
> Paavo Helde schrieb:
>
>> Yes, the c-style cast can be screwed up much more easily! And the
>> results are ill-formed or unspecified if the c-style cast does not
>> correspond to some certain sequences of standard casts. Otherwise, it
>> should be the same though.
>
> Can you elaborate? What do you mean by screwed up more easily? Can you
> provide an example? Can you point me to the part of the standard where
> this is discussed?
The cast notation is discussed in 5.4. It's very formal, but the words
'ill-formed' and 'unspecified' are present in that section. Besides, if
the cast is onlt concerned with constness you could use const_cast and
avoid all the possible doubts related to C-styl casts.
>>> 3. In a class like this:
>>>
>>> class foo {
>>> private:
>>> int *x;
>>> public:
>>> void blah() const {
>>> x[9] = 123;
>>> }
>>> };
>>>
>>> Is it safe to declare blah() const?
>>
>> What you mean by 'safe'? This is valid C++, so I assume it should be
>> 'safe'. Post some real code exhibiting he problem!
>
> By safe in this case I mean: Can the "const" keyword of the blah()
> method introduce trouble when a compiler is doing certain kinds of
> optimization? Appearently this depends on where x is poining to, so I
> clearified my question in response to Alf.
The 'const' qualifier can legally affect the optimizer only if it is the
original object made const. E.g.
const int x = 123;
the optimizer can safely assume that *(&x) will always yield 123, and
substitute 123 for x wherever it feels so. I think it could be the same
for something like:
const int x[10] = {0.1.2.3.4.5.6.7.8.9};
or for
const X x;
with
class X {
int x[10];
// ...
};
Otherwise, if 'const' is used for qualifying the function parameters, for
example, the optimizer cannot assume anything, as there might be other
non-const aliases to the data trough which the data can be altered
legally.
hth
Paavo
E.g. look at
http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
>> And you should avoid C style casts.
>
> What is the difference between a reinterpret_cast and a C-style cast?
A C style cast can perform various kinds casts, a reinterpret_cast only performs
a reinterpret_cast.
>>> I.e. I have a method which can access a foo* r/w - can it also return
>>> (const foo*)x?
>> Sorry, that's a meaningless question: the two things are not related.
>
> Sigh.
Yes.
>>> 2. Is there a difference between const_cast and a c-style cast which
>>> modifies only the const keyword?
>> Yes.
>>
>> You have no guarantee what the C style cast does.
>
> The C style cast yields UB?
Casting often yields UB.
>> And perhaps that's your problem, that you have introduced as
>> reinterpret_cast where you thought you were just adding const. Wouldn't
>> surprise me. Remove all C casts in your code.
>
> There were indeed a few instances where that was the case. I removed
> them, the problem stayed.
How can you be sure you removed them when you're using C style casts.
You can't.
Remove the C style casts.
In that case the constness of foo2::blah is technically correct.
The correctness of the constness of foo1::blah depends on whether x represents
per-instance data or not.
If it does, that is, if the x in foo1 can be replaced with a std::vector<int>,
then the constness of foo1::blah is incorrect, as the compiler will *tell* you
if do change over to std::vector<int>.
>> It's unclear since you have chosen to express the code at the lowest
>> possible level of abstraction
>
> Yes, because that is where it becomes difficult.
It only becomes "difficult" because you're actively removing every clue about
what you're actually trying to do. Unless you want the "difficulty" that's just
stupid. Stop removing information about what you're trying to express, and
voilᅵ, no more "difficulties" -- or at least, greatly reduced frequency.
> It's exactly constructs
> as above that I want to know about, hence my question. This was
> deliberately done so.
>
Huh.
It would make answering easier if you had described in more detail the
problem. "Some very nasty trouble" is not enough to know what's going on
with your program.
If the problem is related to 'const', then one could assume that you
are getting some kind of compiler (or maybe linker) error. However, your
post (rather remotely) implies that what you are getting is a runtime
problem. But what kind of problem? Crashing? Wrong results? What?
Since 'const' is a purely compile-time feature which has basically no
effect on the produced machine code, I would guess that either you have
some other bug in your program (quite probable), probably related to
writing out of boundaries, and it's just showing weird symptoms, as they
tend to do, or maybe it's a compiler bug (unlikely).
> Paavo Helde schrieb:
>
>> Yes, the c-style cast can be screwed up much more easily! And the
>> results are ill-formed or unspecified if the c-style cast does not
>> correspond to some certain sequences of standard casts. Otherwise, it
>> should be the same though.
>
> Can you elaborate? What do you mean by screwed up more easily? Can you
> provide an example? Can you point me to the part of the standard where
> this is discussed?
C-style casts can be screwed up more easily, because it is a kind of
'super cast' that gives the compiler much less room to diagnose possible
problems than with any of the C++ casts (reinterpret_cast included).
As it is a "shut up and do as I tell you" situation, even a simple typo
may go undiagnosed when using a C-style cast, whereas using the
appropriate C++ cast the compiler would have complained loudly.
>
>>> 3. In a class like this:
>>>
>>> class foo {
>>> private:
>>> int *x;
>>> public:
>>> void blah() const {
>>> x[9] = 123;
>>> }
>>> };
>>>
>>> Is it safe to declare blah() const?
>>
>> What you mean by 'safe'? This is valid C++, so I assume it should be
>> 'safe'. Post some real code exhibiting he problem!
>
> By safe in this case I mean: Can the "const" keyword of the blah()
> method introduce trouble when a compiler is doing certain kinds of
> optimization? Appearently this depends on where x is poining to, so I
> clearified my question in response to Alf.
Adding const to a member function only affects members that are
physically part of the class (like x in the example) in what you can do
with them. Members that are not physically part of the class but do
logically belong to the class are unaffected (like the memory that x
refers to).
Adding const to a member without thinking about this distinction between
physical members and logical members can wreak havoc with the
expectations that other classes may have. For example, you could have
the expectation that calling foo:blah() does not change the state of the
foo object, but that expectation would be broken.
But it does not affect in any significant way the optimisations that can
be applied.
>
> Regards,
> Johannes
>
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
Might not 'const' affect the optimizer?
Schobi
That might certainly be the case. If the problem is caused by
optimization (but the code itself is otherwise completely correct), then
it sounds more like a compiler bug.
>>> See the FAQ.
>>
>> I've read the FAQ section about const correctness (actually: in advance
>> to posting here) - I did not find this in there, though. I did not find
>> "const" methods in there either.
>
> E.g. look at
> http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
Ehrm, are you sure that is the right thing? It says "[18.17] Why am I
getting an error converting a Foo** → const Foo**?", the class Foo
mentioned there does not have any method declared const. Am I missing
something here?
>>> And perhaps that's your problem, that you have introduced as
>>> reinterpret_cast where you thought you were just adding const. Wouldn't
>>> surprise me. Remove all C casts in your code.
>>
>> There were indeed a few instances where that was the case. I removed
>> them, the problem stayed.
>
> How can you be sure you removed them when you're using C style casts.
>
> You can't.
>
> Remove the C style casts.
Hey, that's what I wrote: "I remove them [the C-style casts]".
Ahh! Now I get it. You thought I meant "instances" as in "class
instances", but I actually meant "there were cases were I used C-style
casts, I removed them".
English is not my mother language, sorry about the confusion.
>> Never mind the lost memory in foo1 and suppose the static singleton::get
>> returns a pointer to global memory which will never change.
>
> In that case the constness of foo2::blah is technically correct.
>
> The correctness of the constness of foo1::blah depends on whether x
> represents per-instance data or not.
>
> If it does, that is, if the x in foo1 can be replaced with a
> std::vector<int>, then the constness of foo1::blah is incorrect, as the
> compiler will *tell* you if do change over to std::vector<int>.
Thanks for the explanation! I have one more case that I would like to
know about: What if we have a class member int*, which refers to
per-instance data. Then suppose a method returns this raw pointer:
int* foo::getptr1() const {
return x;
}
const int* foo::getptr2() const {
return x;
}
Is getptr1 incorrect vs. the correct getptr2?
>> Yes, because that is where it becomes difficult.
>
> It only becomes "difficult" because you're actively removing every clue
> about what you're actually trying to do. Unless you want the
> "difficulty" that's just stupid. Stop removing information about what
> you're trying to express, and voilà, no more "difficulties" -- or at
> least, greatly reduced frequency.
No, I really do not want to hide any information. I merely am unsure
about exactly those kinds of situations that I described above and
needed clearification (which I got from you, thanks again).
Kind regards,
Johannes
--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verlästerung von Gott, Bibel und mir und bewusster Blasphemie."
-- Prophet und Visionär Hans Joss aka HJP in de.sci.physik
<48d8bf1d$0$7510$5402...@news.sunrise.ch>
Can you provide an example where a C-style cast would just work, but a
reinterpret_cast would fail with a compiler warning/error? I'm curious
because I really am unsure about what the difference between the
reinterpret_cast and C-style cast is.
>> By safe in this case I mean: Can the "const" keyword of the blah()
>> method introduce trouble when a compiler is doing certain kinds of
>> optimization? Appearently this depends on where x is poining to, so I
>> clearified my question in response to Alf.
>
> Adding const to a member function only affects members that are
> physically part of the class (like x in the example) in what you can do
> with them. Members that are not physically part of the class but do
> logically belong to the class are unaffected (like the memory that x
> refers to).
>
> Adding const to a member without thinking about this distinction between
> physical members and logical members can wreak havoc with the
> expectations that other classes may have. For example, you could have
> the expectation that calling foo:blah() does not change the state of the
> foo object, but that expectation would be broken.
Thank you for that clearification, this is what I thought would be the
case (because actually setting x[9] in my above example *does* change
the state of the class, if class management data is stored in x).
> But it does not affect in any significant way the optimisations that can
> be applied.
I thought the const() method keyword was one significant part of
optimization? When the compiler knows the call to the method does not
change the state and there are two (or more) sequential calls to that
method, it might replace those calls with just a single call and reuse
the result over and over.
Kind regards,
Johannes
--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verl�sterung von Gott, Bibel und mir und bewusster Blasphemie."
-- Prophet und Vision�r Hans Joss aka HJP in de.sci.physik
<48d8bf1d$0$7510$5402...@news.sunrise.ch>
> If the problem is related to 'const', then one could assume that you
> are getting some kind of compiler (or maybe linker) error. However, your
> post (rather remotely) implies that what you are getting is a runtime
> problem. But what kind of problem? Crashing? Wrong results? What?
Yes since I explained above the program is far too huge to boil the
problem down. And I can reproduce it only under very certain conditions
(e.g. if I add some debug std::cerrs there, the error disappears). One
of the things that made the problem go away was removing the "const"
keyword of a data chunk class I get (which, btw, uses
std::vector<unsigned char> lying beneath).
So actually this is just the introduction to the question, the problem I
have to find myself. If you're interested anyways: GCC-4.1 runs ok with
-O0, -O1, -O2 (no valgrind issues), -O3 segfaults. GCC-4.3 the same. ICC
never crashes (no valgrind issues either), no matter what optimization
level. This is on x86_64, I actually could try x86_32 (haven't so far).
> Since 'const' is a purely compile-time feature which has basically no
> effect on the produced machine code, I would guess that either you have
> some other bug in your program (quite probable), probably related to
> writing out of boundaries, and it's just showing weird symptoms, as they
> tend to do, or maybe it's a compiler bug (unlikely).
Well, I am not so naive to believe in a compiler bug - although I must
admit that I compared the -O2 and -O3 assembly code and am puzzled about
those vector operations the CPU provides. Back in the days I was used to
the plain old fxyz commands, those seemed easier...
It's possible that the memory layout changes when you add
something like const, but it's not the cause of a memory
corruption bug.
With raw arrays never assume anything. Always check
for illegal index and make sure the array is constructed
before any possible use.
The context?
It was about whether it could be dangerous to add 'const' via a cast.
The above FAQ item illustrates one such situation (although the FAQ is directly
about why the compiler balks when there is no explicit cast: it balks because
it's generally unsafe to add that 'const').
[snip]
> Thanks for the explanation! I have one more case that I would like to
> know about: What if we have a class member int*, which refers to
> per-instance data. Then suppose a method returns this raw pointer:
>
> int* foo::getptr1() const {
> return x;
> }
>
> const int* foo::getptr2() const {
> return x;
> }
>
> Is getptr1 incorrect vs. the correct getptr2?
If what the 'int*' points is indeed per-instance data then you should be able to
replace the 'int*' member with just an 'int' member or a 'std::vector<int>'
member. And with either replacement the compiler will balk at getptr1()
returning a pointer or reference that can be used to modify. Not all 'const'
issues are this simple, but many are: the compiler will tell you, if you just
tells it what it's all about (like, directly using 'int' or 'std::vector<int>').
[ ... ]
> Can you provide an example where a C-style cast would just work, but a
> reinterpret_cast would fail with a compiler warning/error? I'm curious
> because I really am unsure about what the difference between the
> reinterpret_cast and C-style cast is.
While a C-style cast _can_ act like a reinterpret_cast, depending on
the situation, it can also act like a static_cast:
unsigned x = 12u;
int y = (int)x;
If you try to use a reinterpret_cast instead, the compiler should
issue a diagnostic:
unsigned x = 12;
int y = reinterpret_cast<int>(x);
If I compile this with VC++ (for one example), I get:
-----------------------------
reinterpret.cpp(4) : error C2440: 'reinterpret_cast' : cannot convert
from 'unsigned int' to 'int'
Conversion is a valid standard conversion, which can be
performed implicitly or by use of static_cast, C-style cast or
function-style cast
-----------------------------
As implied by the error message, this conversion can even be done
implicitly:
int y = x;
but adding the reinterpret_cast makes it ill formed.
A C-style cast can also act like a const_cast:
int x = 10;
int const &y = x;
int &z1 = (int &)y; // cast away const.
int &z2 = const_cast<int &>(y); // cast away const
int &z3 = reinterpret_cast<int &>(y); // fails.
This time, VC++'s error message reads:
reinterpret.cpp(7) : error C2440: 'reinterpret_cast' : cannot convert
from 'const int' to 'int &'
Reason: cannot convert from 'const int *' to 'int *'
Conversion loses qualifiers
A C-style cast can also combine conversions, for example, producing
results equivalent to a static_cast followed by a const_cast:
class B {};
class D: public B {};
int main() {
D d;
B const *b = &d;
D *d2a = (D *)b;
D *d2b = const_cast<D *>(static_cast<D const *>(b));
return 0;
}
There are also conversions to inaccessible base types that a C-style
cast can do that no new-style cast can. The full list of conversions
you can do with a C-style cast is given in section 5.4 of the
standard.
--
Later,
Jerry.
Const method does not mean that no state is ever changed. The method can
cast away constness, modify the state of some other objects, modify mutable
members, have side effects, etc. So the const keyword does not help
optimizer in this case, in order to be sure that no state is changed it has
to analyze the function body in detail, and then it does not matter if it
has been marked const or not.
AFAIK, the only case where const may affect optimization is by the
declaration of actual objects. If the original object is declared const,
the optimizer has right to assume that the value of the object never
changes (except of data members declared as mutable).
Paavo
Also, the timing can change, with optimization changes, with
adding/removing const (which may affect optimizations), and with adding
debug output.
Gerhard
> Bart van Ingen Schenau schrieb:
>> Johannes Bauer wrote:
>>
>>> Paavo Helde schrieb:
>>>
>>>> Yes, the c-style cast can be screwed up much more easily! And the
>>>> results are ill-formed or unspecified if the c-style cast does not
>>>> correspond to some certain sequences of standard casts. Otherwise,
>>>> it should be the same though.
>>> Can you elaborate? What do you mean by screwed up more easily? Can
>>> you provide an example? Can you point me to the part of the standard
>>> where this is discussed?
>>
>> C-style casts can be screwed up more easily, because it is a kind of
>> 'super cast' that gives the compiler much less room to diagnose
>> possible problems than with any of the C++ casts (reinterpret_cast
>> included).
>
> Can you provide an example where a C-style cast would just work, but a
> reinterpret_cast would fail with a compiler warning/error? I'm curious
> because I really am unsure about what the difference between the
> reinterpret_cast and C-style cast is.
This will compile:
const int i;
(double*)&i;
(double)3.14f;
but this not:
const int i;
reinterpret_cast<double*>(&i);
reinterpret_cast<double>(3.14f);
If you look at clause 5.4 [expr.cast], it is stated that C-style cast
notation can perform the same conversion as
- const_cast
- static_cast
- static_cast followed by const_cast
- reinterpret_cast
- reinterpret_cast followed by const_cast
The C++ casts on the other hand are largely mutually exclusive, so you
have to know much better which conversion you actually want and how safe
that conversion is.
<snip>
>> But it does not affect in any significant way the optimisations that
>> can be applied.
>
> I thought the const() method keyword was one significant part of
> optimization? When the compiler knows the call to the method does not
> change the state and there are two (or more) sequential calls to that
> method, it might replace those calls with just a single call and reuse
> the result over and over.
That kind of thing can only be done if the compiler can prove that the
function is a 'pure' function: it has no side-effects of any kind (no
I/O, no modification of non-member objects, no access of volatile
variables, no calling other (non-pure) functions).
This kind of proof is still outside the capabilities of a C++ compiler.
>
> Kind regards,