Re: On const and the lack thereof
On Jul 7, 2:26 am, Daniel <danielapar...@gmail.com> wrote:
I'm using a third party library that requires providing an
implementation of the following interface.
class ICostFunctor
{
public:
virtual double operator()(const std::vector<double>& v) const = 0;
};
Note that operator() is const, while my implementation will
require passing state as arguments to a C function that will
modify that state. Note also that v is passed as a const
reference to vector<double>, but the C function is expecting
it as a non-const array of double, although it does not modify
it.
An interesting question is why the base class declares this
function const? Is it making copies of it, so that it would
make no sense to modify any derived class members? Or is it
just to allow temporary instances to be passed to the callback.
The signature of the C function is
void costFunction(double *v, int dimv, double *x, int dimx,
void *data);
costFunction doesn't modify v, does modify x, and also
modifies data (after casting back to MyData*.).
So, my working implementation looks like
class CostFunctor : public ICostFunctor
{
public:
// Constructor, destructor
inline
double operator()(const std::vector<double>& v) const
{
costFunction(const_cast<double*>&v[0],
v.size(),
x,
dimx,
data);
...
}
double mutable* x;
int dimx;
mutable MyData* data;
};
This works, my costFunction involves solving a 4 parameter PDE
equation on a 3-dim mesh, and it's happily running as I type.
But, if I change the declaration of the x data member to
mutable double* x;
I get a fault, "trying to write to protected memory", using
Visual Studio 2005.
That is strange, because the two statements are perfectly
identical. (Order is irrelevant in a decl-specifier-seq, and
even things like "long mutable int" are legal.) I knocked up an
extremely simplified version of your code, and I found no
difference in the generated code, regardless of whether I wrote
"double*", "mutable double*", or "double mutable*".
Consistently, and with no other changes. And to specifically
answer your question, it happens when costFunction attempts to
write to x, as you would expect if x were indeed protected
memory.
From the language/compiler point of view, the const on the
object only applies to the declared members themselves, not what
they point to. For what you've described, you shouldn't need
mutable at all. The mutable's you've provided allow modifying
the pointers in a const function (which you don't do). Whether
the CostFunctor objecdt is const or not, you have the right to
modify what the pointers point to, since you haven't declared
them const. (From the language/compiler point of view.
Normally, if the pointed to data is logically part of the
CostFunctor state, then you shouldn't modify it in a const
functions. Your case may be an exception, however, if the const
in ICostFunctor is only to allow temporaries.)
So, my questions are:
1. What is the difference, if any, between "double mutable*" and
"mutable double*"?
Absolutely none.
Is there any language reason why costFunction would see the
first as protected memory and the second as unprotected
memory, given that operator() is const? Is this a language
issue or a compiler implementation issue?
Probably neither. It's certainly not a language issue, and
I suspect that it's not a compiler implementation issue, but
something related to the way you're testing the code.
2. What are the implications of operator() being const?
That the type of "this" is CostFunctor const*, rather than just
CostFunctor*, and that the function can't be called through an
lvalue expression whose type is not const.
I understand that the "this" pointer inside the function
becomes const, but there seems also to be a suggestion that
a call to the operator() not mutate the state of the object,
The suggestion that nothing mutate the state of the object is
*not* a language issue, but simply a convention. The language
doesn't no anything about the state of the object, as such.
There is (or was once---I'm not sure if it survived
standardization) a rule which says that if the actual object is
const, and you attempt to modify it, the code has undefined
behavior (unless the object has user defined
constructors?---that was the original rule). I'm not sure what
the rule is concerning the modification of a temporary object.
But none of that is really relevant here, because as far as the
language is concerned, only the pointers are part of the object,
and not what they point to.
but at the same time nothing stops me from changing the
entries in data member x as long as I'm within the body of
operator(), even if x is not declared mutable. But once
I pass x as an argument to a C function, I'm seeing the
"protected memory" issue, if I haven't declared x as "double
mutable*", in Visual Studio 2005. Is this expected?
Unexpected?
I'd need a complete, compilable example to say more. There's
nothing in what you've posted to explain the behavior you're
describing, and I'm very, very sceptical that it is due to
a compiler error.
--
James Kanze