C++ Logo

std-proposals

Advanced search

Re: The intercept operators

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Sun, 27 Dec 2020 10:22:30 -0500
On Sun, Dec 27, 2020 at 9:43 AM chibane nadir via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Hello Gents,
> I wonder why we cannot allow the overload of the member access operators (. ->) if we know They will be of extreme usefulness.
> Take this case of usage:
> I'm implementing a class called "container_slice", since it is a slice of some class, then it should have all its members, and behave exactly as it (picture a slice of a cake has the same taste of the cake and the same appearance) obviously it should inherit from it.
> I declared it as follow:
>
> template <typename Container>
> class container_slice : public Container
> {
> static_assert(is_container_v<Container>); // metafunction to tell if a class is a standard container, easy to implement
>
> typename Container::iterator m_begin;
> typename Container::iterator m_end;
>
> public:
> using Container::Container; // import all base class constructors
>
> /*
> * this constructor memcpy the container 'c' in the memory allocated for the base class of this instance, and sets the bounds of this
> * slice (the range)
> */
> container_slice(const Container& c, typename Container::iterator _beg, typename Container::iterator _end);
>
> void detach(); // make this slice a separate copy of the range it views.
> typename Container::iterator begin(); // returns: m_begin
> typename Container::iterator end(); // returns: m_end
> };
>
> as you can see, this class has the same member functions of its base class, which allow it to behave as a container and also as a view onto a container ( using this class constructor)
>
> what i want to do is to capture the calls to the base class member functions, like wise when the called member function is modifying (that is change the values or memory address of the referred container) i will call 'detach()' member function, which will copy the range of values it views, from the referred container into a new store to make it a clone (Copy on Write)
>
> There is no way to capture and tell if the called member function is a modifying member function or a const member function. Nor there is a way to do some logic before calling these member functions.
> the only trick that can capture it, is at its call site i.e when we use the (.)member access operator and (->) arrow member access operator. expl:
>
> imagine i can overload the member access operator (.) like the following:
>
> template<typename T, typename Ret, typename ...Args>
> constexpr Ret container_slice::operator . (T container_slice::* member, Args&& ...arg) //the same for operator->
> {
> if constexpr(std::is_const_member_function_pointer<decltype(member)>::value) // meta function easy to implement
> return this->member(std::forward<Args>(arg),...);
> else
> {
> this->detach(); // clone in a separate store (copy on write), then act upon
> return this->member(std::forward<Args>(arg),...);
> }
> }
>
> It is clear that the code above intercept the call to the member function and depending on its nature (const or not) does actions, Like copy on write for example, and there are so many usage with the same technique.
>
> Of course the goal of this, is to avoid writing the same API of the base Container just for the sake of capturing the non 'const' members.
> As you know there are a couple of std-containers and each has a relatively different API. So rewrite each of them is code duplication and a waist of time.
>
> I call this kind of overload: "the intercept operators".
>
> Ok folks, does anyone think that this proposal should be presented to the comity?

Overloading operator-dot has been proposed several times, in many
forms. All of these proposals have eventually died in committee for
various reasons. The last one was 3 years ago.

Note that Stroustrup's operator-dot would not work in your case,
because by default, any `object.name` will access `name` from the
overloaded return type, not from the class of `object`. So if there's
a conflict, the type being proxied has priority. Indeed, in that
proposal, guarantee-ably accessing a member of the proxy object
requires oddball syntax.

Also, your version of operator-dot is weird. Most versions of
operator-dot express their semantics through some form of conversion.
That is, the function return value returns a reference to the proxied
object. Yours seems to want to actually invoke the function call
through a pointer-to-member or something. That seems needlessly
overcomplicated.

N4173 is the first operator-dot paper by Stroustrup, with P0252
providing standard wording for it. P0352 is an alternative idea that
piggybacks off of base class conversions to achieve a similar effect.

Received on 2020-12-27 09:22:44