class member access operator (->) overloading

Discussion in 'C++' started by Arkaitz Jimenez, May 12, 2009.

  1. For what I've seen around the operator-> is normally overloaded to
    return the inner pointer in the case of a SmartPointer template.
    However I was wondering if there is any way of having control after
    the access was done, you can always execute code before returning the
    pointer but obviously you can't after return.
    So, is there anyway to get control before and after operator-> has its
    effect?

    Thanks

    Arkaitz
     
    Arkaitz Jimenez, May 12, 2009
    #1
    1. Advertising

  2. Arkaitz Jimenez wrote:
    > For what I've seen around the operator-> is normally overloaded to
    > return the inner pointer in the case of a SmartPointer template.
    > However I was wondering if there is any way of having control after
    > the access was done, you can always execute code before returning the
    > pointer but obviously you can't after return.
    > So, is there anyway to get control before and after operator-> has its
    > effect?


    If I understand correctly what you're after, then no. The overloaded
    operator-> returns something (usually a pointer) for which another
    operator-> will subsequently be applied. And that's until it's mapped
    to the intrinsic operator-> for a pointer to a class object or a pointer
    to a non-class object for a pseudo-destructor call.

    #include <iostream>
    #include <ostream>

    using std::cout;

    template<class T>
    class AuxHasArrow
    {
    T* t;
    public:
    AuxHasArrow(T* t) : t(t) {}

    T* operator->() { std::cout << "In Aux\n"; return t; }
    };

    template<class T>
    class HasArrow
    {
    T* t;
    public:
    HasArrow(T* t) : t(t) {}
    AuxHasArrow<T> operator->()
    { std::cout << "In HasArrow\n"; return AuxHasArrow<T>(t); }
    };

    struct A {
    int a;
    };

    int main()
    {
    A a = { 42 };
    HasArrow<A> ha(&a);

    cout << ha->a << "after all\n";
    }

    See, there is nothing you can squeeze in your class to capture the
    control after the operator-> is applied to the address of the 'a' object
    (to extract that 42 for output).

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, May 12, 2009
    #2
    1. Advertising

  3. Stuart Golodetz wrote:
    > Arkaitz Jimenez wrote:
    >> For what I've seen around the operator-> is normally overloaded to
    >> return the inner pointer in the case of a SmartPointer template.
    >> However I was wondering if there is any way of having control after
    >> the access was done, you can always execute code before returning the
    >> pointer but obviously you can't after return.
    >> So, is there anyway to get control before and after operator-> has its
    >> effect?
    >>
    >> Thanks
    >>
    >> Arkaitz

    >
    > What sort of control are you after? If you just want to execute some
    > code after the return, I guess you could always just return an instance
    > of another class with an overloaded operator->, which itself executes
    > some code and returns the actual pointer. That code would then be
    > executing after the original return.


    I believe Arkaitz would like to have some code executed after the
    intrinsic operator-> is applied to the [actual] pointer (that the op->
    returns). I don't think this is possible from within the same class.

    > But I'm not sure I understand the
    > motivation for doing this in the first place...


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, May 12, 2009
    #3
  4. > If I understand correctly what you're after, then no.  The overloaded
    > operator-> returns something (usually a pointer) for which another
    > operator-> will subsequently be applied.  And that's until it's mapped
    > to the intrinsic operator-> for a pointer to a class object or a pointer
    > to a non-class object for a pseudo-destructor call.
    >
    > ....
    > ....
    > See, there is nothing you can squeeze in your class to capture the
    > control after the operator-> is applied to the address of the 'a' object
    > (to extract that 42 for output).
    >
    > V


    Well, that was my idea, that it couldn't be done, at least the way I
    wanted to.

    Thanks

    Arkaitz
     
    Arkaitz Jimenez, May 12, 2009
    #4
  5. > What sort of control are you after? If you just want to execute some
    > code after the return, I guess you could always just return an instance
    > of another class with an overloaded operator->, which itself executes
    > some code and returns the actual pointer. That code would then be
    > executing after the original return. But I'm not sure I understand the
    > motivation for doing this in the first place...
    >
    > Regards,
    > Stu


    Well, from what I know it's not possible, but just wondering if any
    other trick was available.

    The idea would be for example to wrap and mutexprotect one object
    before and after a member is accessed or a method is executed.

    Wraped<myobject> wrapobj;
    wrapobj->whatever();
    --------------------------
    template operator -> would do:

    mutex_lock(objolock);
    wrapobj->called_method();
    mutex_unlock(objlock);

    Clearly there is no way of doing that with operator overloading, that
    I know at least, but wanted to ask.


    Thanks

    Arkaitz
     
    Arkaitz Jimenez, May 12, 2009
    #5
  6. Arkaitz Jimenez

    SG Guest

    On 12 Mai, 15:23, Arkaitz Jimenez <> wrote:
    > For what I've seen around the operator-> is normally overloaded to
    > return the inner pointer in the case of a SmartPointer template.
    > However I was wondering if there is any way of having control after
    > the access was done, you can always execute code before returning the
    > pointer but obviously you can't after return.
    > So, is there anyway to get control before and after operator-> has its
    > effect?


    Something like this?


    struct do_nothing { void pre(){}; void post(){} };

    template<typename T, typename U = T*,
    typename prepost_func = do_nothing>
    class ptrproxy
    {
    T* ptr;
    public:
    explicit ptrproxy(T* p) : ptr(p)
    { prepost_func().pre(); }

    ~ptrproxy()
    { prepost_func().post(); }

    U operator->() const {return U(ptr);}
    };

    template<typename T, typename PrePost>
    struct funky_pointer_metaf {
    typedef ptrproxy<T,ptrproxy<T,T*,PrePost> > type;
    };

    #include <iostream>

    struct S {
    void blah()
    { std::cout << " --- S::blah ---\n"; }
    };

    struct my_prepost {
    void pre() { std::cout << "prior access\n"; }
    void post() { std::cout << "after access\n"; }
    };

    int main() {
    S s;
    typedef funky_pointer_metaf<S,my_prepost>::type funky_t;
    funky_t p (&s);
    p->blah();
    p->blah();
    }

    which outputs:

    prior access
    --- S::blah ---
    after access
    prior access
    --- S::blah ---
    after access

    ?

    Cheers!
    SG
     
    SG, May 12, 2009
    #6
  7. >   struct do_nothing { void pre(){}; void post(){} };
    >
    >   template<typename T, typename U = T*,
    >     typename prepost_func = do_nothing>
    >   class ptrproxy
    >   {
    >     T* ptr;
    >   public:
    >     explicit ptrproxy(T* p) : ptr(p)
    >     { prepost_func().pre(); }
    >
    >     ~ptrproxy()
    >     { prepost_func().post(); }
    >
    >     U operator->() const {return U(ptr);}
    >   };
    >
    >   template<typename T, typename PrePost>
    >   struct funky_pointer_metaf {
    >     typedef ptrproxy<T,ptrproxy<T,T*,PrePost> > type;
    >   };
    >
    >   #include <iostream>
    >
    >   struct S {
    >     void blah()
    >     { std::cout << " --- S::blah ---\n"; }
    >   };
    >
    >   struct my_prepost {
    >     void pre()  { std::cout << "prior access\n"; }
    >     void post() { std::cout << "after access\n"; }
    >   };
    >
    >   int main() {
    >     S s;
    >     typedef funky_pointer_metaf<S,my_prepost>::type funky_t;
    >     funky_t p (&s);
    >     p->blah();
    >     p->blah();
    >   }
    >
    > which outputs:
    >
    >   prior access
    >    --- S::blah ---
    >   after access
    >   prior access
    >    --- S::blah ---
    >   after access
    >
    > ?
    >
    > Cheers!
    > SG


    Ok, It certainly does what I was looking for, lets see if I understand
    it correctly.
    You create a temporary sptr inside the original sptr return, that way
    you can execute code using the temporary constructor and destructor
    routines.
    Smart, with this kind of method I'd only need to be careful to not use
    throwable code inside the code intended to be executed after the call,
    isn't it?

    Thanks

    Arkaitz
     
    Arkaitz Jimenez, May 12, 2009
    #7
  8. SG wrote:
    > On 12 Mai, 15:23, Arkaitz Jimenez <> wrote:
    >> For what I've seen around the operator-> is normally overloaded to
    >> return the inner pointer in the case of a SmartPointer template.
    >> However I was wondering if there is any way of having control after
    >> the access was done, you can always execute code before returning the
    >> pointer but obviously you can't after return.
    >> So, is there anyway to get control before and after operator-> has its
    >> effect?

    >
    > Something like this?
    >
    >
    > struct do_nothing { void pre(){}; void post(){} };
    >
    > template<typename T, typename U = T*,
    > typename prepost_func = do_nothing>
    > class ptrproxy
    > {
    > T* ptr;
    > public:
    > explicit ptrproxy(T* p) : ptr(p)
    > { prepost_func().pre(); }
    >
    > ~ptrproxy()
    > { prepost_func().post(); }
    >
    > U operator->() const {return U(ptr);}
    > };
    >
    > template<typename T, typename PrePost>
    > struct funky_pointer_metaf {
    > typedef ptrproxy<T,ptrproxy<T,T*,PrePost> > type;
    > };
    >
    > #include <iostream>
    >
    > struct S {
    > void blah()
    > { std::cout << " --- S::blah ---\n"; }
    > };
    >
    > struct my_prepost {
    > void pre() { std::cout << "prior access\n"; }
    > void post() { std::cout << "after access\n"; }
    > };
    >
    > int main() {
    > S s;
    > typedef funky_pointer_metaf<S,my_prepost>::type funky_t;
    > funky_t p (&s);
    > p->blah();
    > p->blah();
    > }
    >
    > which outputs:
    >
    > prior access
    > --- S::blah ---
    > after access
    > prior access
    > --- S::blah ---
    > after access
    >
    > ?


    Nice!

    It takes advantage of the extra indirection of the operator-> to return
    the proxy temporary which will call the post-processing stuff in its
    destructor that will be called *at the end of full expression*. I
    thought about this, but hadn't find the *temporary* solution, for some
    reason I was hung up on local objects, which get destroyed before the
    final operator-> is used...

    Thank you.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, May 12, 2009
    #8
  9. * Victor Bazarov:
    > SG wrote:
    >> On 12 Mai, 15:23, Arkaitz Jimenez <> wrote:
    >>> For what I've seen around the operator-> is normally overloaded to
    >>> return the inner pointer in the case of a SmartPointer template.
    >>> However I was wondering if there is any way of having control after
    >>> the access was done, you can always execute code before returning the
    >>> pointer but obviously you can't after return.
    >>> So, is there anyway to get control before and after operator-> has its
    >>> effect?

    >>
    >> Something like this?
    >>
    >>
    >> struct do_nothing { void pre(){}; void post(){} };
    >>
    >> template<typename T, typename U = T*,
    >> typename prepost_func = do_nothing>
    >> class ptrproxy
    >> {
    >> T* ptr;
    >> public:
    >> explicit ptrproxy(T* p) : ptr(p)
    >> { prepost_func().pre(); }
    >>
    >> ~ptrproxy()
    >> { prepost_func().post(); }
    >>
    >> U operator->() const {return U(ptr);}
    >> };
    >>
    >> template<typename T, typename PrePost>
    >> struct funky_pointer_metaf {
    >> typedef ptrproxy<T,ptrproxy<T,T*,PrePost> > type;
    >> };
    >>
    >> #include <iostream>
    >>
    >> struct S {
    >> void blah()
    >> { std::cout << " --- S::blah ---\n"; }
    >> };
    >>
    >> struct my_prepost {
    >> void pre() { std::cout << "prior access\n"; }
    >> void post() { std::cout << "after access\n"; }
    >> };
    >>
    >> int main() {
    >> S s;
    >> typedef funky_pointer_metaf<S,my_prepost>::type funky_t;
    >> funky_t p (&s);
    >> p->blah();
    >> p->blah();
    >> }
    >>
    >> which outputs:
    >>
    >> prior access
    >> --- S::blah ---
    >> after access
    >> prior access
    >> --- S::blah ---
    >> after access
    >>
    >> ?

    >
    > Nice!
    >
    > It takes advantage of the extra indirection of the operator-> to return
    > the proxy temporary which will call the post-processing stuff in its
    > destructor that will be called *at the end of full expression*. I
    > thought about this, but hadn't find the *temporary* solution, for some
    > reason I was hung up on local objects, which get destroyed before the
    > final operator-> is used...
    >
    > Thank you.


    SG didn't provide a reference, but Bjarne once wrote a paper about exactly the
    above technique.

    So, let's also thank Bjarne Stroustrup.

    Of course, some soul that-I-don't-recall-the-name-of at Microsoft should perhaps
    also be thanked for the "COM call interceptor" which, even though it's not only
    system specific but also technology specific, for what it does is more general.

    And then also thanks to the folks at ParkPlace for the even more general C++
    language extension or preprocessor or whatever it was that provides general call
    interceptors for implemention of cross-code concerns (like e.g. logging); they
    also should be thanked for the Smalltalk project when they were at Xerox PARC.

    Argh, I cannot remember the name for that last technique!


    Cheers,

    - Alf


    --
    Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
    No ads, and there is some C++ stuff! :) Just going there is good. Linking
    to it is even better! Thanks in advance!
     
    Alf P. Steinbach, May 12, 2009
    #9
  10. Arkaitz Jimenez

    SG Guest

    On 12 Mai, 16:39, "Alf P. Steinbach" <> wrote:
    >
    > SG didn't provide a reference


    Right. I can't take credit for that (except for the attempt to use
    exactly one class template instead of two with overloaded operator->()
    to shorten the example). But I have no reference handy. I think I saw
    it on someone's blog where the author used it for locking a mutex. I
    probably wouldn't use it for locking, though.

    > but Bjarne once wrote a paper about exactly the
    > above technique.
    >
    > So, let's also thank Bjarne Stroustrup.


    Is it publicly available?

    Cheers!
    SG
     
    SG, May 12, 2009
    #10
  11. > Well, off the top of my head, return a proxy object whose constructor
    > locks the mutex and whose destructor unlocks it. In addition, the proxy
    > object should have an operator-> that returns a pointer to the actual
    > object.
    >
    > But be careful: this is rarely the right approach for robust
    > multi-threaded applications. If you've determined that it's what you
    > need, fine; but if it's more a "wouldn't it be nice to be able to do
    > this" thing, then you might want to think about it some more. Usually
    > what's needed is locking higher up: lock, read some data from one
    > object, store the data in another object, unlock. In that sequence,
    > individual locks on the read and the write are pointless.
    >
    > --
    >    Pete
    > Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
    > "The Standard C++ Library Extensions: a Tutorial and Reference"
    > (www.petebecker.com/tr1book)


    Yeah, I know its not a good practice for multithreading, it was just
    an example actually.
    The implementation you suggest is coded in this same thread by SG and
    it works perfectly.

    Thanks

    Arkaitz
     
    Arkaitz Jimenez, May 12, 2009
    #11
  12. * SG:
    > On 12 Mai, 16:39, "Alf P. Steinbach" <> wrote:
    >> SG didn't provide a reference

    >
    > Right. I can't take credit for that (except for the attempt to use
    > exactly one class template instead of two with overloaded operator->()
    > to shorten the example). But I have no reference handy. I think I saw
    > it on someone's blog where the author used it for locking a mutex. I
    > probably wouldn't use it for locking, though.
    >
    >> but Bjarne once wrote a paper about exactly the
    >> above technique.
    >>
    >> So, let's also thank Bjarne Stroustrup.

    >
    > Is it publicly available?


    Bjarne Stroustrup: Generalizing Overloading for C++. Overload, Issue 25, April
    1, 1998. Also, Chinese Translation. Programmer Magazine, April 1, 2002.
    <url: http://www.research.att.com/~bs/wrapper.pdf>

    It references
    Michael Tiemann: "Wrappers:" Solving the RPC problem in GNU C++. Proceedings of
    the USENIX C++ Conference, Denver, CO. October 1988.

    Don't know what the April 1 publication dates mean, though.


    Cheers,

    - Alf (Google master)

    --
    Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
    No ads, and there is some C++ stuff! :) Just going there is good. Linking
    to it is even better! Thanks in advance!
     
    Alf P. Steinbach, May 12, 2009
    #12
  13. Arkaitz Jimenez

    SG Guest

    On 12 Mai, 17:59, "Alf P. Steinbach" <> wrote:
    > * SG:
    > > On 12 Mai, 16:39, "Alf P. Steinbach" <> wrote:
    > >> So, let's also thank Bjarne Stroustrup.

    > > Is it publicly available?

    >
    > Bjarne Stroustrup: Generalizing Overloading for C++. Overload, Issue 25, April
    > 1, 1998. Also, Chinese Translation. Programmer Magazine, April 1, 2002.
    > <url:http://www.research.att.com/~bs/wrapper.pdf>


    You mean
    B. Stroustrup: Wrapping C++ Member Function Calls. The C++ Report.
    June 2000, Vol 12/No 6. Code used for efficiency comparisons.

    Thanks for the link. :) I must have used the wrong keywords for the
    search.

    Cheers!
    SG
     
    SG, May 12, 2009
    #13
  14. Arkaitz Jimenez wrote:

    > Ok, It certainly does what I was looking for, lets see if I understand
    > it correctly.
    > You create a temporary sptr inside the original sptr return, that way
    > you can execute code using the temporary constructor and destructor
    > routines.


    Yes, that is correct.

    > Smart, with this kind of method I'd only need to be careful to not use
    > throwable code inside the code intended to be executed after the call,
    > isn't it?


    Yes. Like with any class, it is a bad idea to throw an exception from a
    destructor.

    >
    > Thanks
    >
    > Arkaitz


    Bart v Ingen Schenau
    --
    a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
    c.l.c FAQ: http://c-faq.com/
    c.l.c++ FAQ: http://www.parashift.com/c -faq-lite/
     
    Bart van Ingen Schenau, May 12, 2009
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,786
    Thomas Weidenfeller
    Oct 12, 2005
  2. Thomas
    Replies:
    3
    Views:
    453
    DaKoadMunky
    Sep 21, 2004
  3. Siemel Naran
    Replies:
    4
    Views:
    808
    Micah Cowan
    Jan 12, 2005
  4. ghager
    Replies:
    6
    Views:
    623
    ghager
    Jan 19, 2006
  5. Replies:
    11
    Views:
    735
    James Kanze
    May 16, 2007
Loading...

Share This Page