Thread: Template overload of operator ++/--

  1. #1
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654

    Template overload of operator ++/--

    I'd like to do an overlord of operator ++ and -- for my class with templates, like this:
    Code:
    template<typename T> CValueHandler& operator ++ ();
    But the thing is, that while it compiles fine, I can't call that overloaded operator.

    Code:
    SomeClass myClass;
    myClass++;
    Compiler simply complains it can't find a suitable overload.
    So, my question is, is it possible to overload ++/-- and use templates too? I can't seem to find a good place to fit in a template type either:

    Code:
    SomeClass myClass;
    myClass<UINT64>++;
    Doesn't work either.
    Using Visual Studio 2005.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    http://new-brunswick.net/workshop/c+...html#faq-13.14
    You overloaded the prefix form, yet tried to use the postfix form.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Oh, I see. Thanks for the answer.
    I refine it to
    Code:
    template<typename T> void operator ++ (int);
    But it still won't let me compile since it can't determine the value of T:
    Code:
    Error	5	error C2783: 'void CSyncClass::CValueHandler::operator ++(int)' : could not deduce template argument for 'T'
    Code:
    rTemp<UINT64>++;
    Still doesn't work.
    So any more tips?
    Last edited by Elysia; 10-21-2007 at 08:38 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Returning void from an overloaded ++ function is neither of the options listed in the FAQ.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    From what I see in the FAQ, either it's:

    Code:
    Number  operator++ (int); // postfix ++
    or
    Code:
    void    operator++ (int);
    So I changed it to:
    Code:
    template<typename T> CValueHandler& operator ++ (); // Prefix
    template<typename T> CValueHandler& operator -- (); // Prefix
    template<typename T> CValueHandler operator ++ (int); // Postfix
    template<typename T> CValueHandler operator -- (int); // Postfix
    Prefix returns a reference of itself; the new data is returned.
    Postfix returns a copy of itself before the new data is acquired, so it returns old data.
    That's how it's supposed to work, from what I understand.

    For that matter, I just want to be able to get the code actually compiling since I can't deduce the template T argument.
    Last edited by Elysia; 10-21-2007 at 08:38 AM.

  6. #6
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    If you want it to return void.
    Try like this
    Code:
    #include <iostream>
    using namespace std;
    
    template <class T>
    class Number {
    public:
        Number():data() {}
        void operator ++ ()  { data ++; }
        T & get() { return data; }
        template <class U> friend  ostream & operator << ( ostream &, const Number<U> & );
    private:
        T data;
    };
    
    template <class U> 
    ostream & operator << ( ostream &str , const Number<U> & u ) {
        str << u.data;
        return str;
    }
    
    int main() {
        Number<int> n;
        cout << n << endl;
        ++n;
        cout << n << endl;
    }
    Kurt

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Let's forget about the operators for now... I need, or want, to know if it's possible to call the overloaded operators when there's no argument that takes T. Which is my main problem; the code won't compile because it can't deduce T.

  8. #8
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by Elysia View Post
    Let's forget about the operators for now... I need, or want, to know if it's possible to call the overloaded operators when there's no argument that takes T. Which is my main problem; the code won't compile because it can't deduce T.
    This statement doesn't make much sense without context.
    Show some code.
    Kurt

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Class CValueHandler - the one with the overloaded operators.
    Code:
    class CValueHandler
    {
    	...
    	template<typename T> CValueHandler& operator ++ (); // Prefix
    	template<typename T> CValueHandler& operator -- (); // Prefix
    	template<typename T> CValueHandler operator ++ (int); // Postfix
    	template<typename T> CValueHandler operator -- (int); // Postfix
    	...
    };
    Sync is declared as:
    Code:
    CSyncClass Sync;
    Which has an overload that returns a CValueHandler&:
    Code:
    class CSyncClass
    {
    	...
    	const CValueHandler& operator [] (CString strName);
    	...
    };
    And here's what I try to do - call operator ++ (postfix):
    Code:
    UINT64 n = Sync["nNumOfDirs"]++;
    (Of course, it's just test code yet.)
    Which gives me the error:
    Code:
    error C2783: 'CSyncClass::CValueHandler CSyncClass::CValueHandler::operator ++(int)' : could not deduce template argument for 'T'
    Last edited by Elysia; 10-21-2007 at 09:15 AM.

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You can tell it like that
    Code:
    a.operator++<int>();
    But then the syntax is so ugly that you might use a regular member function.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Will keep in mind. Any other ways it might work?

  12. #12
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Don't make operator++ . Making operator ++ a template member function doesn't make sense.

    If anything you can make a template cast operator, so that the reference returned by operator++ can be convertible to any comparable type.

    Or just make the whole class a template.

    It all depends on what you are trying to do.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The whole idea was to make a thread-safe class that could store memory kind of like a linked list. Problem was that the memory was stored in raw form and no type information was available, so the operator ++ had to know the type of the data (hence the template) in order to cast the memory to the correct type and increase it.
    I'm thinking this is a bit of a problem and there's probably easier ways to do it. For one, storing type information might be done, but it's just that it's so prone to errors since there's so many different types of data that can be stored.

    Code:
    class CSyncClass
    {
    public:
    	enum eDataType
    	{
    		TYPE_CHAR,
    		TYPE_BYTE,
    		TYPE_INT16,
    		TYPE_UINT16,
    		TYPE_INT32,
    		TYPE_UINT32,
    		TYPE_INT64,
    		TYPE_UINT64,
    		TYPE_CSTRING,
    		TYPE_CHARP,
    		TYPE_BYTEP,
    		TYPE_INT16P,
    		TYPE_UINT16P,
    		TYPE_INT32P,
    		TYPE_UINT32P,
    		TYPE_INT64P,
    		TYPE_UINT64P,
    		TYPE_CSTRINGP
    	};
    
    	class CBufferValueInfo
    	{
    		CString strValueName; // Name of the stored data block
    		eDataType DataType;   // Type of data stored
    		UINT32 nBlockOffset;  // Offset in memory where data is stored
    		UINT32 nBlockSize;    // Total size of the data block where the data is stored
    		UINT32 nDataSize;	  // Size of data (elements of an array) (eg if data = char & this = 4, then there's 4 chars)
    		bool bAllocated;      // If true, then data is stored here; if false, then the block is free
    	};
    
    	class CValueHandler
    	{
    	private:
    		friend class CSyncClass;
    		CBufferValueInfo* pValue;
    
    	public:
    		//template<typename T> CValueHandler operator + (T tData);
    		//template<typename T> CValueHandler operator - (T tData);
    		//template<typename T> CValueHandler operator * (T tData);
    		//template<typename T> CValueHandler operator / (T tData);
    		template<typename T> CValueHandler& operator += (T tData);
    		template<typename T> CValueHandler& operator -= (T tData);
    		template<typename T> CValueHandler& operator *= (T tData);
    		template<typename T> CValueHandler& operator /= (T tData);
    		CValueHandler& operator ++ (); // Prefix
    		CValueHandler& operator -- (); // Prefix
    		CValueHandler operator ++ (int); // Postfix
    		CValueHandler operator -- (int); // Postfix
    		template<typename T> CValueHandler& operator = (T tData);
    		//template<typename T> operator T;
    	};
    
    	CSyncClass();
    	~CSyncClass();
    	template<typename T> void SetValue(CString strName, T tData, UINT32 nSize = 0);
    	template<typename T> T GetValue(CString strName, UINT32 nSize = 0);
    	//template<typename T> void IncValue(CString strName);
    	//template<typename T> void DecValue(CString strName);
    	const CValueHandler& operator [] (CString strName);
    
    private:
    	CValueHandler m_Value;
    	pp<BYTE> m_pBuffer; // Array to hold memory
    	CMapStringToPtr m_LookupMap; // Array containing info of stored values, looked up by name
    	CMap<DWORD, DWORD, CBufferValueInfo*, CBufferValueInfo*> m_BlockLookupMap; // Array containing info of stored values, looked up by offset
    	UINT32 m_nBufferSize;
    	CCriticalSection cSync;
    
    	template<typename T> eDataType GetDataType(T tData);
    	template<typename T> DWORD GetSize(T& tData);
    	template<typename T> bool IsNumType(T& tData)
    	{
    		if ( typeid(tData) == typeid(UINT8) || typeid(tData) == typeid(INT8) || typeid(tData) == typeid(UINT16) || typeid(tData) == typeid(INT16) || typeid(tData) == typeid(UINT32) || 
    			 typeid(tData) == typeid(INT32) || typeid(tData) == typeid(UINT64) || typeid(tData) == typeid(INT64) || typeid(tData) == typeid(float) || typeid(tData) == typeid(double) )
    		{
    			return true;
    		}
    		else
    		{
    			return false;
    		}
    	}
    };

  14. #14
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    So does the each instance of the list store Values of the same, or can a single list hold multiple types?

    If the former, you just need to make your list a template, and take all those templates out of the member functions.

    If the latter, you have a more complex problem on your hands. You can't just have you increment and decrement receive a type because the element incremented or decremented to won't necessarily be of the same type. The way to have a list store different types is to use inheritance. Your list would be a list of generic objects. Then have each type inherit from this generic object type. For primitives this requires a warper object that can easily be implemented as a template.

    Another option in the later case is to use unions. I'm only mentioning this for completeness. Inheritance is preferred because it is type safe. However, unions are slightly faster because the implementation requires you to figure out which type is stored instead of figuring out on its own.
    Last edited by King Mir; 10-21-2007 at 03:39 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It's a single class to hold multiple values in one big huge block of memory, by converting it to BYTE* (ie raw) and storing it along with type information.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  2. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 12:54 PM