Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic type conversion for templates with const/non-const pointer types

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?

like image 567
Ian Avatar asked May 02 '16 21:05

Ian


1 Answers

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

like image 69
nwp Avatar answered Nov 06 '22 03:11

nwp