Why is an array argument treated as a const array? - c++

I am working with a member function that just sets the object's internal orientation to the values given in the argument:
void A::SetOrientation(float a[3]);
In another class, I have the following:
class B
{
public:
RestoreStateTo(A* const o_pA) const
private:
float d_orientation[3];
};
void
B::RestoreStateTo(A* const o_pA) const
{
o_pA->SetOrientation(d_orientation);
}
I get the following compiler error (with Visual Studio 2010):
error C2664: 'void A::SetOrientation(float [])' : cannot convert parameter 1 from 'const float [3]' to 'float []'
I found that I can avoid the issue with o_pA->SetOrientation(const_cast<float *>(d_orientation));, but I'd like to get a better grasp of what is going on.
I would appreciate an explanation as to why the array argument is converted to a const array as well as suggest the right approach to dealing with the error?

Because the prototype of your function void B::RestoreStateTo(A* const o_pA) const says you will not modify any member of B.
Since d_orientation is an attribute of B, it is const in this function.

Your SetOrientation function should take in a const,
void A::SetOrientation(const float a[3]);
Otherwise, it's possible that A::SetOrientation will modify the array you pass in. Because you have "B::RestoreStateTo(A* const o_pA) const", it means that the compiler won't let you pass a pointer to B::d_orientation as a non-const input, because A::SetOrientation has no guarantee not to modify it.

You have declared a const member function, and therefore all the members of this will be treated as const inside that function. So it shouldn't be surprising that d_orientation is treated as const.
It's the same principle that makes this code illegal:
const B* p = ...;
p->d_orientation[0] = 0.0f; // error, assigning member of `const` object

Related

Compiler seeming to change my const parameter [duplicate]

This question already has answers here:
constant pointer vs pointer on a constant value [duplicate]
(11 answers)
C++: combine const with template arguments
(6 answers)
Closed 6 years ago.
I am trying to use my template class's Contains() method, but I am getting a strange argument conversion error.
error C2664: 'bool DynamicArray::Contains(const E) const'
: cannot convert argument 1 from 'const Joint *' to 'Joint *const '
with E=Joint
Conversion loses qualifiers
Here is the relevant template class code.
template <class E>
class DynamicArray
{
bool Contains (const E element) const;
// Other code...
};
template <class E>
bool DynamicArray<E>::Contains(const E element) const
{
// Other code...
}
The call made to the Contains method is done so here
bool ASMState::AnimatesJoint(const Joint* pJoint) const
{
return m_animatedJoints.Contains(pJoint);
}
Relevant template class code in ASMState.h
class ASMState
{
DynamicArray<Joint*> m_animatedJoints;
// Other members...
bool AnimatesJoint(const Joint* pJoint) const;
// Other methods...
};
If I remove the const in the AnimatesJoint function signature like so, bool ASMState::AnimatesJoint(Joint* pJoint) const then the code compiles. I would like to keep the const there if I can, but I do not know why that parameter seems to change from what I wrote. That is, from const Joint * to Joint *const according to the compiler.
I am using Visual Studio 2013 Express
Your class template DynamicArray deduces the type E as Joint *, and in the member function Contains you basically add a const to it. Now, as it was mentioned in the comments and already stated by the compiler error, this does not lead to const Joint* (which is the same as Joint const*), but rather to Joint * const -- adding a const does not correspond to a textual replacement where you'd simply replace E by your pointer type.
However, the problem here is not in adding the const to the pointer type taken by the function Contains, because this cast is allowed. The problem is rather that you pass a const pointer to the function Contains, but it is actually expecting a non-const pointer -- it's the cast from const Joint* to Joint * that is disallowed.
This is why removing the const in Contains(const E) will not solve this specific problem. I'd strongly suggest it nevertheless, because taking a parameter by const-value is almost never useful.
Rather, as you've already written, you need to remove the const in the function AnimatesJoint(const Joint* pJoint).
It seems that bool Contains (const E element) const expects an input of type const E, whereas in
return m_animatedJoints.Contains(pJoint);
you are passing an input of type const E *, in other words a pointer. Perhaps the solution is to change this line to:
return m_animatedJoints.Contains(*pJoint);
I guess that the error you are getting is because the compiler is trying to pass the input pJoint as const E where E = ... * const, i.e. a constant pointer.

error: invalid conversion from 'char**' to 'const char**' [duplicate]

I've got a function that requires const some_type** as an argument (some_type is a struct, and the function needs a pointer to an array of this type). I declared a local variable of type some_type*, and initialized it. Then I call the function as f(&some_array), and the compiler (gcc) says:
error: invalid conversion from ‘some_type**’ to ‘const some_type**’
What's the problem here? Why can't I convert a variable to const?
See: Why can't I pass a char ** to a function which expects a const char **? from the comp.lang.c FAQ.
You have a few options to get around what jamesdlin outlined in his answer.
You could use an intermediate variable.
some_type const* const_some_array = some_array;
f(&const_some_array);
You could change the parameters of f.
void f(some_type const* const* some_array);
You probably need to specify some more context, for instance is the argument passed data into or out of (or both?) the function?
Try making your variable const as well:
some_type const *some_array = ....;
This reads as "some_array is a pointer to a const some_type". The code can't modify the thing being pointed at. So you have to declare your variable const before passing it to the function.
(Edited...)

is there a way to pass this as const?

I have a class of items and a function that returns it's size.
I have the operator == which gets 2 const parameters of the class type and return the result of item1.size() == item2.size (). size function is non-parametres func and need only hidden this parameter.
The problem is when I try to use size on const reference of classes, it's give me an error:
'function' : cannot convert 'this' pointer from 'type1' to 'type2'
The compiler could not convert the this pointer from type1to type2.
This error can be caused by invoking a non-const member function on a const object. Possible resolutions:
Remove the const from the object declaration.
Add const to the member function.
The piece of code as it is on my problem:
bool operator==(const CardDeck& deck1, const CardDeck& deck2){
if (deck1.size() != deck2.size()) {
return false;
}
//...
}
The error:
'unsigned int CardDeck::size(void)' : cannot convert 'this' pointer from 'const CardDeck' to 'Cardeck&'
If I want that size will get the object as const, I must make it friend and pass the object as const refference or is there a way to tell size get the class type this as constant ???
Thanks for helping.
Most likely you forgot to qualify the size member function as const: size_t size() const { return /* compute/return size */; }
The alternative is that you really did typo CardDeck as Cardeck somewhere (the spelling from your error message).

Pointer to a const member variable

I was wondering what the syntax was for a pointer to a constant member variable.
I know a pointer to a non-const member function and a pointer to a const member function are expressly different types, ie, the following are two distinct types:
typedef void (Foo::*Bar)(void);
typedef void (Foo::*ConstBar)(void) const;
I was wondering if the same could be said of pointers to non-const and const member variables, ie are the following two distinct types as well, and if so, what is the syntax of the latter:
typedef int (Foo::*var);
typedef int (Foo::*constVar) const; // Not the correct syntax.
Thanks.
The type of the pointer-to-member needs to match the type of the member:
typedef int (Foo::*var); // pointer to a data member of type 'int'
typedef const int (Foo::*cvar); // pointer to a data member of type 'const int'
The const-qualification of a member function is a part of its type, just like the return type is a part of its type.
Just to make it funnier:
typedef const int (Foo::*(Foo::*ConstBar)(void) const);
ConstBar is a pointer to a const-member function taking no arguments and returning a pointer to a const-member of type int.
A general tip of how to remember the syntax in your question: you just write it the way you would define the member of the class
void name(void) const; // const function
const int name; // const member
And then replace name by (Foo::*name), resulting in:
void (Foo::*name)(void) const; // pointer to const function
const int (Foo::*name); // pointer to const member

pointer assignment

I have the following template structure:
template <typename scalar_type>
struct postc_params{
scalar_type delta;
unsigned int time_horizon;
matrix_math::matrix<scalar_type> dynamics;
boost::shared_ptr<continuous_set> invariant_set_ptr;
boost::shared_ptr<continuous_set> input_set_ptr;
boost::shared_ptr<continuous_set> initial_set_ptr;
};
Now, I have a templated class with a private member of the above structure type
template <typename scalar_type>
class A{
....
private:
....
postc_params<scalar_type> my_postc;
};
Inside a member function definition of class A, I have the following line of code:
my_postc.initial_set_ptr = my_postc.initial_set_ptr->transform(some_obj);
transform function returns a pointer of type
boost::shared_ptr<continuous_set>
With this code, I have the following error:
passing 'const boost::shared_ptr' as 'this' argument of 'boost::shared_ptr< >& boost::shared_ptr< >::operator=
(const boost::shared_ptr&) [with Y = const continuous::continuous_set, T = continuous::continuous_set]' discards qualifiers
Can anyone help me out with the cause?
Is the member function in A const?
If I am reading your code right, you are trying to change a member of a class from a const member function which is not allowed. Either remove the const from the member function or make the member mutable.
So,
mutable postc_params<scalar_type> my_postc;
However, I would take care with this method. Maybe reevaluate why the method that is changing my_postc is const. Either it should not be const or it should not be changing my_postc.
you are trying to assign to a const pointer as per the error message: "passing 'const boost::shared_ptr' as 'this' argument"
the member function you mention is surely const hence the error
you should rather reconsider your design than throw mutable here and there in your code.