Implicit conversions are not considered for objects of member function calls, including the subscript operator overload.
Consider the consequences if that were allowed: Every single time any undeclared member function is called like this, the compiler would have to figure out all the types that the object can be converted to (note that any other otherwise unrelated type could have a converting constructor), and check if that has declared the missing member function. Not to mention how confusing that would be for the reader of the code (the conversion might be obvious in your conversion operator case, but not in the converting constructor case, and as far as I know, they are not otherwise treated differently).
So is there a notationally convenient way to get Prop to behave the way I want
You would have to define a member function for each of the member function of vector that you want to pass pass through transparently. Here is the subscript operator as an example:
auto operator[](std::size_t pos) {
return value[pos];
}
auto operator[](std::size_t pos) const {
return value[pos];
}
The problem is of course that all wrapped member functions must be explicitly declared. Another problem is arguments whose type depend on T
. For example, vector::operator[]
uses vector::size_type
, which might not be defined for all T
that you might use (certainly not for float
). Here we make a compromise and use std::size_t
.
A less laborious way of creating such "transparent" wrapper is inheritance. A publicly inheriting template would automatically have all the member functions of the parent and be implicitly convertible to it and can be referred by pointers and references of parent type. However, the transparency of such approach is a bit problematic mainly because ~vector
is not virtual.
Private inheritance allows same wrapping as your member approach, but with much nicer syntax:
template<typename T>
struct Prop : private T
{
using T::operator[];
using T::T;
};
Note that inheritance approach prevents you from using fundamental types as T
. Also, it makes the implicit conversion impossible (even with conversion operator) , so you cannot use Prop
as T
in free functions that expect T
.
PS. Note that your conversion operator returns a value, so the vector must be copied, which may be undesirable. Consider providing reference versions instead:
operator T&&()&& { return *this; }
operator T&()& { return *this; }
operator const T&() const& { return *this; }