2

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

ZFect
  • 47
  • 1
  • 4
  • 1
    The question is not a duplicate, as the problem leading to the compiler error is not solved by one of the linked threads. It's not the `Joint *` to `Joint * const` conversion which leads to the error, but the invalid `Joint const *` to `Joint *` conversion. And the latter issue is not different than for any other (non-pointer) type. – davidhigh Oct 21 '16 at 20:18

2 Answers2

1

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).

davidhigh
  • 14,652
  • 2
  • 44
  • 75
-2

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.

space_voyager
  • 1,984
  • 3
  • 20
  • 31