Reputation: 872
Is it possible to provide an automatic conversion for a template class instantiated with const and non-const pointer types?
Specifically, consider the following:
template <typename T>
class A {
public:
operator A<const T>()
{
return A<const T>();
}
};
int main()
{
A<const int> a1;
A<int> a2;
// Works fine; invokes operator A<const T>()
a1 = a2;
A<const int*> a3;
A<int*> a4;
// Fails to compile: no viable overloaded '='
a3 = a4;
return 0;
}
Is it possible to provide an explicit conversion for types with pointer template arguments? What would this look like in the definition of A?
As a bonus/background question, why does the above work for non-pointer template arguments, but not for pointer template arguments?
Upvotes: 6
Views: 874
Reputation: 9991
The source of the confusion is the constness of the pointer vs the constness of the pointee. The setup you have now converts a T
into a const T
. If you substitute int
for T
it works, int
becomes const int
. However, if you substitute int *
you get int * const
, not const int *
. The T
gets a const
, which is a pointer, so the pointer becomes const
, not the object pointed to.
The following code works:
A<int*const> a5;
A<int*> a6;
// compiles
a5 = a6;
You can do some tricky things like
operator A<std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>>()
{
return {};
}
to make a3 = a4;
compile, but you have to be very careful that these conversions actually do what they are supposed to do (the above example incorrectly(?) allows int
to const int *
conversion because remove_pointer
does nothing if the given type is not a pointer, would need to enable_if
+ is_pointer
which gets complicated rather quickly).
Upvotes: 4