Transparent temporaries..?
-
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[^] -
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[^]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 likeTempX.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 -
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 likeTempX.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 sumBadKarma 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[^]
-
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[^]
You can decrease the level of complexity by changing the -> operator in the CInvisibleTemporary class from
CArbitraryClass**&** operator->() { return m_ArbitraryObject; }
toCArbitraryClass***** operator->() { return **&**m_ArbitraryObject; }
the code for calling is nowWrapper.operator ->()->DoFoo();
in stead ofWrapper.operator ->().operator ->().DoFoo();
codito ergo sum -
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[^]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
-
You can decrease the level of complexity by changing the -> operator in the CInvisibleTemporary class from
CArbitraryClass**&** operator->() { return m_ArbitraryObject; }
toCArbitraryClass***** operator->() { return **&**m_ArbitraryObject; }
the code for calling is nowWrapper.operator ->()->DoFoo();
in stead ofWrapper.operator ->().operator ->().DoFoo();
codito ergo sumThank you! The following change did the trick:
BadKarma wrote:
CArbitraryClass**&** operator->() { return m_ArbitraryObject; }
toCArbitraryClass***** 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[^]