Related types?
As you know, T* and const T* are related types. There is a standard conversion from first to second (qualification conversion).
First, you must understand that A<T> and A<const T> not common types. These types can have different sizes, views and purposes. You can define, but not another.
In particular, A<const T> not a constant A<T> , so there is no qualification conversion between them, and C ++ does not declare user-friendly qualification conversions flexibly. (A user cannot declare a standard transformation, only a user-defined transformation โ a user-defined transformation is not a standard transformation.)
Thus, user-defined types are fundamentally different from the basic types: they cannot be related to how the basic types exist.
shared_ptr<>
shared_ptr<> intended to create a family of compatible types: shared_ptr<T> implicitly converted to shared_ptr<U> if if T* implicitly converted to U* . In particular, shared_ptr<T> implicitly converted to shared_ptr<const T> . It is also implicitly converted to shared_ptr<void> , so for the same reason.
Since the types shared_ptr<const T> and shared_ptr<T> not connected in any special way, the conversion from shared_ptr<T> to shared_ptr<const T> does not differ from shared_ptr<T> to shared_ptr<void> . These are just two different conversions, but none of them can be considered โpreferredโ in any context, unlike the conversion from T* to const T* (rank = exact match), which is preferable to converting from T* to void* (rank = conversion).
Function Templates
Some standard conversions for argument function arguments are allowed:
- qualification transformations
- some pointer conversions: derivatives to the base
- ...
But, as we have seen, such transformations do not exist between the shared_ptr<> types.
This means that even if the compiler was allowed to list all possible types for the template parameter in order to include the function template
template <typename V> void f (shared_ptr<const T> v1);
into an endless set of function prototypes:
for every type T, such that shared_ptr<const T> can be instantiated: f (shared_ptr<const T>)
if you donโt have an exact match, you wonโt be able to call the function: given the ads
struct Base {}; struct Derived : Base {}; shared_ptr<Derived> d;
Among the many prototypes f :
f (shared_ptr<const Base>) f (shared_ptr<const Derived>)
therefore, calling f (d) will be ambiguous, since both of these candidates are associated with different user transformations.