Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Transparent temporaries..?

Transparent temporaries..?

Scheduled Pinned Locked Moved C / C++ / MFC
comdata-structurestoolsjsonhelp
6 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Bob Stanneveld
    wrote on last edited by
    #1

    Hello, I have the following problem. I want to create a temporary object that is transparent to the caller of the function which creates the temporary. We all know that a temporary object is created on the stack for objects returned by value from a function. I wan't to use this property of the temporary to create a locking / unlocking mechanism for an object. See the following code for details

    // this class will be used by the user of the API
    // In the actual code it will be a template parameter.
    class CArbitraryClass
    {
    public:
    void DoFoo() {}
    };

    // this is the wrapper that the user uses to store CArbitraryClass objects
    class CWrapperClass
    {
    public:
    // will return a temporary object which the user doesn't know or sees
    CInvisibleTemporary operator->()
    {
    return CInvisibleTemporary::CInvisibleTemporary();
    }
    };

    // this object is the 'invisible' temporary. It should pass on the
    // stored object (CArbitraryClass). The user should not have to
    // call any extra functions for it.
    class CInvisibleTemporary
    {
    public:
    CArbitraryClass& operator->() { return m_ArbitraryObject; }

    private:
    CArbitraryClass m_ArbitraryObject;
    };

    So the code should look like the following statements: CWrapperClass Wrapper; Wrapper->DoFoo(); But it looks like: CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo(); Am I trying to do something impossible? Behind every great black man...             ... is the police. - Conspiracy brother Blog[^]

    B 2 Replies Last reply
    0
    • B Bob Stanneveld

      Hello, I have the following problem. I want to create a temporary object that is transparent to the caller of the function which creates the temporary. We all know that a temporary object is created on the stack for objects returned by value from a function. I wan't to use this property of the temporary to create a locking / unlocking mechanism for an object. See the following code for details

      // this class will be used by the user of the API
      // In the actual code it will be a template parameter.
      class CArbitraryClass
      {
      public:
      void DoFoo() {}
      };

      // this is the wrapper that the user uses to store CArbitraryClass objects
      class CWrapperClass
      {
      public:
      // will return a temporary object which the user doesn't know or sees
      CInvisibleTemporary operator->()
      {
      return CInvisibleTemporary::CInvisibleTemporary();
      }
      };

      // this object is the 'invisible' temporary. It should pass on the
      // stored object (CArbitraryClass). The user should not have to
      // call any extra functions for it.
      class CInvisibleTemporary
      {
      public:
      CArbitraryClass& operator->() { return m_ArbitraryObject; }

      private:
      CArbitraryClass m_ArbitraryObject;
      };

      So the code should look like the following statements: CWrapperClass Wrapper; Wrapper->DoFoo(); But it looks like: CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo(); Am I trying to do something impossible? Behind every great black man...             ... is the police. - Conspiracy brother Blog[^]

      B Offline
      B Offline
      BadKarma
      wrote on last edited by
      #2

      Hi, Bob, its normal that you should write CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo(); because after each function .operator ->() call you have returned a other object temporary, pointer or reference. From this object you can call again some functions and so on. The first call (Wrapper.operator ->()) returns the temp object 'TempX' (CInvisibleTemporary) You have now a object from which you can call some functions like TempX.operator ->() which returns a reference to the encapsulted object (CArbitraryClass m_ArbitraryObject) and now you can call the finale funtion DoFoo(); If you want to encapsulate the function call list, you will have to return the correct object immediatly. But then you could lose the transparancy you need. Maybe this could be done by using templates. I will check this out!! codito ergo sum

      B 1 Reply Last reply
      0
      • B BadKarma

        Hi, Bob, its normal that you should write CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo(); because after each function .operator ->() call you have returned a other object temporary, pointer or reference. From this object you can call again some functions and so on. The first call (Wrapper.operator ->()) returns the temp object 'TempX' (CInvisibleTemporary) You have now a object from which you can call some functions like TempX.operator ->() which returns a reference to the encapsulted object (CArbitraryClass m_ArbitraryObject) and now you can call the finale funtion DoFoo(); If you want to encapsulate the function call list, you will have to return the correct object immediatly. But then you could lose the transparancy you need. Maybe this could be done by using templates. I will check this out!! codito ergo sum

        B Offline
        B Offline
        Bob Stanneveld
        wrote on last edited by
        #3

        BadKarma wrote:

        its normal that you should write CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo();

        I know that I should write this and I want to avoid this obfuscation by introducing the invisible temporary. My current solution is that the user has to create the temporary himself by calling a function from the wrapper class. This is OK, but if the user doesn't destroy the object, the cache I use it for, might get polluted. I'll let you know if I find a solution. Thanks for your time, really appreciate it! :-D Behind every great black man...             ... is the police. - Conspiracy brother Blog[^]

        B 1 Reply Last reply
        0
        • B Bob Stanneveld

          BadKarma wrote:

          its normal that you should write CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo();

          I know that I should write this and I want to avoid this obfuscation by introducing the invisible temporary. My current solution is that the user has to create the temporary himself by calling a function from the wrapper class. This is OK, but if the user doesn't destroy the object, the cache I use it for, might get polluted. I'll let you know if I find a solution. Thanks for your time, really appreciate it! :-D Behind every great black man...             ... is the police. - Conspiracy brother Blog[^]

          B Offline
          B Offline
          BadKarma
          wrote on last edited by
          #4

          You can decrease the level of complexity by changing the -> operator in the CInvisibleTemporary class from CArbitraryClass**&** operator->() { return m_ArbitraryObject; } to CArbitraryClass***** operator->() { return **&**m_ArbitraryObject; } the code for calling is now Wrapper.operator ->()->DoFoo(); in stead of Wrapper.operator ->().operator ->().DoFoo(); codito ergo sum

          B 1 Reply Last reply
          0
          • B Bob Stanneveld

            Hello, I have the following problem. I want to create a temporary object that is transparent to the caller of the function which creates the temporary. We all know that a temporary object is created on the stack for objects returned by value from a function. I wan't to use this property of the temporary to create a locking / unlocking mechanism for an object. See the following code for details

            // this class will be used by the user of the API
            // In the actual code it will be a template parameter.
            class CArbitraryClass
            {
            public:
            void DoFoo() {}
            };

            // this is the wrapper that the user uses to store CArbitraryClass objects
            class CWrapperClass
            {
            public:
            // will return a temporary object which the user doesn't know or sees
            CInvisibleTemporary operator->()
            {
            return CInvisibleTemporary::CInvisibleTemporary();
            }
            };

            // this object is the 'invisible' temporary. It should pass on the
            // stored object (CArbitraryClass). The user should not have to
            // call any extra functions for it.
            class CInvisibleTemporary
            {
            public:
            CArbitraryClass& operator->() { return m_ArbitraryObject; }

            private:
            CArbitraryClass m_ArbitraryObject;
            };

            So the code should look like the following statements: CWrapperClass Wrapper; Wrapper->DoFoo(); But it looks like: CWrapperClass Wrapper; Wrapper.operator ->().operator ->().DoFoo(); Am I trying to do something impossible? Behind every great black man...             ... is the police. - Conspiracy brother Blog[^]

            B Offline
            B Offline
            BadKarma
            wrote on last edited by
            #5

            Hi, bob If you mean invisible (like hide the class/object from the user) instead of transparent (don't care for the object class type), I may have a solution that works like you intended.

            class CArbitraryClass
            {
            public:
            void DoFoo() {}
            };
            
            class CInvisibleTemporary
            {
            public:
            CInvisibleTemporary(void (CArbitraryClass::*pFunction)()) 
            {
            // TODO: implement locking
            (m_ArbitraryObject.*pFunction)();
            }
            
            private:
            CArbitraryClass m_ArbitraryObject;
            };
            
            class CWrapperClass
            {
            public:
            void Call(void (CArbitraryClass::*p)()) 
            { 
            CInvisibleTemporary::CInvisibleTemporary(p);
            }
            };
            

            The way you need to call it is like this:

            CWrapperClass Wrapper;
            Wrapper.Call(CArbitraryClass::DoFoo);
            

            The function Call does create a temporary object of the type CInvisibleTemporary. To this object the function that needs to be called is given via its constructor. The 'invisible' temporary object doens't exist anymore after the 'Call', which frees the locked resoruces. I hope that this may be a solution or at least sets you on route to one :) codito ergo sum

            1 Reply Last reply
            0
            • B BadKarma

              You can decrease the level of complexity by changing the -> operator in the CInvisibleTemporary class from CArbitraryClass**&** operator->() { return m_ArbitraryObject; } to CArbitraryClass***** operator->() { return **&**m_ArbitraryObject; } the code for calling is now Wrapper.operator ->()->DoFoo(); in stead of Wrapper.operator ->().operator ->().DoFoo(); codito ergo sum

              B Offline
              B Offline
              Bob Stanneveld
              wrote on last edited by
              #6

              Thank you! The following change did the trick:

              BadKarma wrote:

              CArbitraryClass**&** operator->() { return m_ArbitraryObject; } to CArbitraryClass***** operator->() { return **&**m_ArbitraryObject; }

              The compiler now automatically calls the second operator->() and everything looks like you have no temporary object! I tested this syntax on VS2005 and I don't know if it works on previous versions of visual studio. I'll try it as soon when I get my hands on one of those versions. I first tried it with implicit casting, but this didn't work. I now have the solution thanks to you. :-D Behind every great black man...             ... is the police. - Conspiracy brother Blog[^]

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups