Code review

This is a discussion on Code review within the C++ Programming forums, part of the General Programming Boards category; But I especially hate non-member functions other than operators. Yes, in that I agree....

  1. #31
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    But I especially hate non-member functions other than operators.
    Yes, in that I agree.

  2. #32
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    This seems like a non-argument. After all myobj == "something" is still valid using a non-member equality operator; you're not forced out of your habit. There isn't a logical problem with "something" == myobj either.

  3. #33
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    But in any case, the non-member operators are giving me problem, just as the templates are.
    The linker is error happy today.


    Update on this nasty problem:
    The global += operators are at fault, but I don't know why.

    Inside the namespace Strings or not, it won't compile.
    Template function:
    Code:
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, const T* strData)
    	{
    		rlhs.AppendStr(strData);
    		return rlhs;
    	}
    Sample code to use operator +=:
    Code:
    	test += L"This is a test";
    Gives linking error: undefined symbol.
    class Strings::CTmplStringBase<wchar_t,class Strings::StrTraits<wchar_t> > & __cdecl Strings::operator+=(class Strings::CTmplStringBase<wchar_t,class Strings::StrTraits<wchar_t> > &,wchar_t const *)" is undefined.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #34
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Inside the namespace Strings or not, it won't compile
    Gives linking error: undefined symbol.
    Linker error or compiler error?

    Maybe the problem is that the operator '+=' does not exist. You might think it does, but only its template exists. What if you try specializing the template function with the type of 'test' ?
    (I might be wrong on this)

    Further, you might consider using

    1) only one template argument for the operator, which then calls a function in a template class. Simple reason: function templates cannot have (yet) default arguments, while template classes can.

    or,

    2) don't use the trait as template parameter. Simply parametrize the trait by the first parameter and use the type in the trait as the return type.

    Code:
    	template<typename T> 
                CTmplStringBase<typename Traits<T>::myIdentifier>& //return type
                    operator += ( CTmplStringBase<typename Traits<T>::myIdentifier>& rlhs, const T* strData) { // blah}
    Note that the 'typename' is necessary to overcome a language ambiguity: do you use the trait as you defined earlier, you mean the static variable. Then don't use 'typename'. Do you use the trait as I suggested, then use 'typename': you mean the type.
    Last edited by MarkZWEERS; 05-10-2008 at 10:28 AM.

  5. #35
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Code:
    	template<> CTmplStringBase< wchar_t, Strings::StrTraits<wchar_t> >& operator += (CTmplStringBase< wchar_t, Strings::StrTraits<wchar_t> >& rlhs, const wchar_t* strData)
    	{
    		//rlhs.AppendStr(strData);
    		return rlhs;
    	}
    This, too, fails to work. It parses the template fine, but still gives a linking error.
    This seems over my head -_-

    I'm guessing that these are wrong:
    Code:
    		friend CTmplStringBase& operator += (CTmplStringBase& rlhs, const T* strData);
    		friend CTmplStringBase& operator += (CTmplStringBase& rlhs, const T cData);
    		friend CTmplStringBase& operator += (CTmplStringBase& rlhs, uint64_t nData);
    		friend CTmplStringBase& operator += (CTmplStringBase& rlhs, int64_t nData);
    		friend CTmplStringBase& operator += (CTmplStringBase& rlhs, long nData);
    (From inside class.)
    If not specified, the code won't compile (compile error).
    And if they do exist, it will give linking error - or in other words, they seem to refer to a function that does not exist.
    Last edited by Elysia; 05-10-2008 at 10:30 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #36
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    I'm guessing that these are wrong:
    (From inside class.)
    Did you implement all the functions you declared 'friend' in your class?

  7. #37
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Yes, of course. One of them is posted above, but I still get linking errors about that one and all the others.


    It has really come to this...
    This operator, defined as global is found and used:

    Code:
    template<typename T> CTmplStringBase< T, Strings::StrTraits<T> >& operator += (CTmplStringBase< T, Strings::StrTraits<T> >& rlhs, const T* strData)
    {
    	rlhs.AppendStr(strData);
    	return rlhs;
    }
    ...But doesn't work because it's not declared as a friend.
    So, the problem is how to declare it as a friend inside the class, since it so obviously won't work.

    This:
    Code:
    friend CTmplStringBase< T, Strings::StrTraits<T> >& operator += (CTmplStringBase< T, Strings::StrTraits<T> >& rlhs, const T* strData);
    Seems to take precedence over the global operator and so the compiler uses this instead. Only the problem is that it cannot find the function and therefore I get a linking error.

    Any ideas on how to do this? Without making the whole operator(s) inline?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #38
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Haha the error is nice:

    Code:
    template<typename T> CTmplStringBase<T>::CTmplStringBase(const T* strData)
    {
        *this = strData;
    }
    But the operator= is not defined yet! That you do lateron. So don't use '*this = strData' , but copy data members one-by-one. Then it works on my machine!

    Further, I really really think you should not derive from your structs, because
    1) it does not satisfy at all the Liskov substitution principle (just learned, but very useful)
    2) it isn't a trait, and if it was so, traits are always template parameters.

    You'd better have a composition: make a private/protected object of it in your string class.

    http://www.ubookcase.com/book/Addiso...3586/ch34.html

    it is really worth looking at this chapter.

    Please find attached what I have made (very simplified) from your code.
    Attached Files Attached Files

  9. #39
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Quote Originally Posted by MarkZWEERS View Post
    Haha the error is nice:

    Code:
    template<typename T> CTmplStringBase<T>::CTmplStringBase(const T* strData)
    {
        *this = strData;
    }
    But the operator= is not defined yet! That you do lateron. So don't use '*this = strData' , but copy data members one-by-one. Then it works on my machine!
    I don't think that really matters because operator = is defined later (and besides, the definition comes first, so the compiler knows there is an operator =). Plus before breaking out the operators, the code passed every test in the suite, so it's in no way wrong.
    But does it matter if it's inherited, just placed as an object or the members just made static so I can access them as a namespace? I did the latter, because it seems more efficient (I only need one instance of every member of the trait class).

    Here's in the newest code I'm trying with.
    Attached Files Attached Files
    Last edited by Elysia; 05-10-2008 at 11:40 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #40
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    well, it made THE difference for the very simple test files I've attached above...
    Code:
    #include "markStringEx.h"
    #include "markStringExImpl.h"
    
    int main()
    {
      CTmplStringBase<int> example1;
      CTmplStringBase<int> example2( 10);
      CTmplStringBase<int> example3( example2); // gave _linker_ error
    
      return 0;
    }
    The copy constructor call gave the error that no symbol for '=' was found:

    mark@zweers:~/progs/CPP/tests_and_tryouts/Strings/test$ make testString
    g++ -O3 -Wall -ansi -I.. -c testString.C
    ../markStringExImpl.h: In function ‘int main()’:
    g++ -I.. -O3 -Wall -ansi -o testString testString.o -L.. -lTests
    testString.o: In function `main':
    testString.C: (.text+0x25): undefined reference to `CTmplStringBase<int>:: operator=(int)'
    testString.C: (.text+0x34): undefined reference to `CTmplStringBase<int>:: operator=(CTmplStringBase<int> const&)'
    collect2: ld returned 1 exit status
    make: *** [testString] Error 1

  11. #41
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Didn't for me, it didn't. But the problem is the friend operators. Especially +=. I just can't get them declared as friends without causing a linking errors.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #42
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Didn't for me, it didn't.
    What compiler are you using? I guess a Microsoft compiler, which is known to accept more than the gnu or sun compilers/linkers. I'm using g++-4.3 . Sometimes it gives errors in very early stages, preventing difficult to track errors lateron.

    Can you attach a simplified library with only one friend function which causes the error?

  13. #43
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    VS's default compiler is what I use. 2008 edition, so it's top of the line.
    I'll attach the dumbed down class. Just remove all the comments if you want to shrink it in size.
    Construct an object, then add a string literal +=, and you will get either a linking error or ambiguous error (I left two += operators there, you can check them).
    Attached Files Attached Files
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #44
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,409
    This code... has so very much wrong with it. The code... the concepts... ;_;

    Eventually I just decided to post the code as fixed rather than waste time telling you everything, but I highly suggest you read everything with extreme care: unless I missed something every single change is crucial to successful compilation.

    You also should probably get a good stingy C++ compiler. Obviously whatever you are using isn't informing you of all the problems that it should be telling you about.

    I hope you have a differencing program installed.

    Soma

    Code:
    //#if defined(_AFXEXT) && !defined(STRINGEXIMPL_H)
    //#error "Dll code must include StringExImpl.h"
    //#endif
    
    #ifndef STRINGEX_H__FILE__
    #define STRINGEX_H__FILE__
    
    //#include "boost\operators.hpp"
    
    namespace Strings
    {
      template<typename T, typename Traits> class CTmplStringBase;
      template<typename T, typename Traits> CTmplStringBase<T,Traits>& operator += (CTmplStringBase<T,Traits>& rlhs, const T* strData);
      template<typename T, typename Traits> CTmplStringBase<T,Traits>& operator += (CTmplStringBase<T,Traits>& rlhs, const T cData);
      template<typename T, typename Traits> CTmplStringBase<T,Traits>& operator += (CTmplStringBase<T,Traits>& rlhs, uint64_t nData);
      template<typename T, typename Traits> CTmplStringBase<T,Traits>& operator += (CTmplStringBase<T,Traits>& rlhs, int64_t nData);
      template<typename T, typename Traits> CTmplStringBase<T,Traits>& operator += (CTmplStringBase<T,Traits>& rlhs, long nData);
      template<typename T, typename Traits> bool operator == (CTmplStringBase<T,Traits>& rlhs, const T* strData);
      template<typename T, typename Traits> bool operator == (CTmplStringBase<T,Traits>& rlhs, const T cData);
      template<typename T, typename Traits> bool operator != (CTmplStringBase<T,Traits>& rlhs, const T* strData);
      template<typename T, typename Traits> bool operator != (CTmplStringBase<T,Traits>& rlhs, const T cData);
    
    	template<typename T> class StrTraits
    	{
    	//protected:
    	public:
    		typedef int (fnc_tprintf_s)(T* buffer, size_t sizeOfBuffer, const T* format, ...);
    		typedef int (fnc_tvprintf_s)(T* buffer, size_t sizeOfBuffer, const T* format, va_list argptr);
    		typedef int (fnc_tcscmp)(const T* string1, const T* string2);
    		typedef int (fnc_tvcprintf)(const T* format, va_list argptr);
    
    		static const T* UINT64_T_IDENTIFIER;
    		static const T* INT64_T_IDENTIFIER;
    		static const T* LONG_IDENTIFIER;
    
    		static uint32_t GetLength(const T* strData); // { return strlen(strData); }
    		static fnc_tprintf_s* GetFormatFunction(const T*);
    		static fnc_tvprintf_s* GetVFormatFunction(const T*);
    		static fnc_tvcprintf* GetVFormatCountFunction(const T*);
    		static fnc_tcscmp* GetCompareFunction(const T*);
    	};
    
    	//template<typename T> uint32_t StrTraits<T>::GetLength(const T* strData) const { return strlen(strData); }
    
    	template<typename T, typename Traits> class CTmplStringBase: 
    		//private StrTraits<T>, 
    		public boost::addable<CTmplStringBase<T, Traits>, const T*>,
    		public boost::addable<CTmplStringBase<T, Traits>, const T>,
    		public boost::addable<CTmplStringBase<T, Traits>, uint64_t>,
    		public boost::addable<CTmplStringBase<T, Traits>, int64_t>,
    		public boost::addable<CTmplStringBase<T, Traits>, long>,
    		public boost::addable< CTmplStringBase<T, Traits> >
    #ifdef _MFC_VER
    		, public boost::addable< CTmplStringBase<T, Traits>, const CStringT< T, StrTraitMFC_DLL<T> > >
    #endif
    		{
    	public:
    		CTmplStringBase();
    		CTmplStringBase(const CTmplStringBase& rSrc);
    #ifdef _MFC_VER
    		CTmplStringBase(const CStringT< T, StrTraitMFC_DLL<T> >& strSrc);
    #endif
    		CTmplStringBase(const T* strData);
    		CTmplStringBase(const T cData);
    		CTmplStringBase(uint64_t nData);
    		CTmplStringBase(int64_t nData);
    		CTmplStringBase(long nData);
    		~CTmplStringBase();
    		CTmplStringBase& operator = (const T* strData);
    		CTmplStringBase& operator = (const T cData);
    		CTmplStringBase& operator = (uint64_t nData);
    		CTmplStringBase& operator = (int64_t nData);
    		CTmplStringBase& operator = (long nData);
    		CTmplStringBase& operator = (const CTmplStringBase& rSrc);
    #ifdef _MFC_VER
    		CTmplStringBase& operator = (const CStringT< T, StrTraitMFC_DLL<T> >& rSrc);
    #endif
    		friend CTmplStringBase<T,Traits>& operator += <> (CTmplStringBase<T,Traits>& rlhs, const T* strData);
    		friend CTmplStringBase<T,Traits>& operator += <> (CTmplStringBase<T,Traits>& rlhs, const T cData);
    		friend CTmplStringBase<T,Traits>& operator += <> (CTmplStringBase<T,Traits>& rlhs, uint64_t nData);
    		friend CTmplStringBase<T,Traits>& operator += <> (CTmplStringBase<T,Traits>& rlhs, int64_t nData);
    		friend CTmplStringBase<T,Traits>& operator += <> (CTmplStringBase<T,Traits>& rlhs, long nData);
    		friend bool operator == <> (CTmplStringBase<T,Traits>& rlhs, const T* strData);
    		friend bool operator == <> (CTmplStringBase<T,Traits>& rlhs, const T cData);
    		friend bool operator != <> (CTmplStringBase<T,Traits>& rlhs, const T* strData);
    		friend bool operator != <> (CTmplStringBase<T,Traits>& rlhs, const T cData);
    		operator const T* () const;
    		void Replace(const CTmplStringBase& strReplaceWhat, const CTmplStringBase& strReplaceWith);
    		CTmplStringBase Right(uint32_t nCount) const;
    		void Delete(uint32_t nStartFrom, uint32_t nCount = 0);
    		uint32_t GetLength() const;
    		T* GetBuffer(uint32_t nMinSize);
    		void ReleaseBuffer();
    		void Truncate(uint32_t nNewSize);
    		int32_t Find(const T* strFind, uint32_t nBeginAt = 0) const;
    		int32_t Find(const T cFind, uint32_t nBeginAt = 0) const;
    		CTmplStringBase Mid(uint32_t nStart, uint32_t nCount = 0) const;
    		void Format(const T* strFormat, ...);
    		void AppendFormat(const T* strFormat, ...);
    		void Empty();
    
    	private:
    		void Init();
    		int32_t ReplaceInternal(const CTmplStringBase& strReplaceWhat, const CTmplStringBase& strReplaceWith, bool bReplace);
    		void FormatInternal(const T* strFormat, va_list arg);
    		void CopyStr(const T* strData);
    		void AppendStr(const T* strData);
    		void CopyStrLowLevel(T* strDst, uint32_t nDstSize, const T* strSrc, T** pUnusedPtr) const;
    		void PrepareBuffer(uint32_t nNeededSize);
    		template<typename Type> CTmplStringBase& Assign(Type& Data);
    		template<typename Type> CTmplStringBase& AppendNum(Type& Data, const T* strFormat);
    		T* m_pData;
    		T* m_pUnusedStart;
    		uint32_t m_nSize; // Number of elements in m_pData
    		static const uint32_t nDefaultSize = 10;
    	};
    
    	//template<typename T> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, const T* strData);
    	//template<typename T> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, const T cData);
    	//template<typename T> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, uint64_t nData);
    	//template<typename T> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, int64_t nData);
    	//template<typename T> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, long nData);
    	//template<typename T> bool operator == (CTmplStringBase<T, Traits>& rlhs, const T* strData);
    	//template<typename T> bool operator == (CTmplStringBase<T, Traits>& rlhs, const T cData);
    	//template<typename T> bool operator != (CTmplStringBase<T, Traits>& rlhs, const T* strData);
    	//template<typename T> bool operator != (CTmplStringBase<T, Traits>& rlhs, const T cData);
    
    //#ifndef STRINGEXIMPL_H
    //	template<> class __declspec(dllimport) CTmplStringBase<wchar_t>;
    //	template<> class __declspec(dllimport) CTmplStringBase<char>;
    //	template<> class __declspec(dllimport) StrTraits<wchar_t>;
    //	template<> class __declspec(dllimport) StrTraits<char>;
    //	template<> class __declspec(dllimport) Strings::StrTraits<char>;
    //	template<> __declspec(dllimport) CTmplStringBase<char>& operator += (CTmplStringBase<char>& rlhs, const char* strData);
    //	template<> __declspec(dllimport) CTmplStringBase<char>& operator += (CTmplStringBase<char>& rlhs, const char cData);
    //	template<> __declspec(dllimport) CTmplStringBase<char>& operator += (CTmplStringBase<char>& rlhs, uint64_t nData);
    //	template<> __declspec(dllimport) CTmplStringBase<char>& operator += (CTmplStringBase<char>& rlhs, int64_t nData);
    //	template<> __declspec(dllimport) CTmplStringBase<char>& operator += (CTmplStringBase<char>& rlhs, long nData);
    //	template<> __declspec(dllimport) bool operator == (CTmplStringBase<char>& rlhs, const char* strData);
    //	template<> __declspec(dllimport) bool operator == (CTmplStringBase<char>& rlhs, const char cData);
    //	template<> __declspec(dllimport) bool operator != (CTmplStringBase<char>& rlhs, const char* strData);
    //	template<> __declspec(dllimport) bool operator != (CTmplStringBase<char>& rlhs, const char cData);
    //	template<> __declspec(dllimport) CTmplStringBase<wchar_t>& operator += (CTmplStringBase<wchar_t>& rlhs, const wchar_t* strData);
    //	template<> __declspec(dllimport) CTmplStringBase<wchar_t>& operator += (CTmplStringBase<wchar_t>& rlhs, const wchar_t cData);
    //	template<> __declspec(dllimport) CTmplStringBase<wchar_t>& operator += (CTmplStringBase<wchar_t>& rlhs, uint64_t nData);
    //	template<> __declspec(dllimport) CTmplStringBase<wchar_t>& operator += (CTmplStringBase<wchar_t>& rlhs, int64_t nData);
    //	template<> __declspec(dllimport) CTmplStringBase<wchar_t>& operator += (CTmplStringBase<wchar_t>& rlhs, long nData);
    //	template<> __declspec(dllimport) bool operator == (CTmplStringBase<wchar_t>& rlhs, const wchar_t* strData);
    //	template<> __declspec(dllimport) bool operator == (CTmplStringBase<wchar_t>& rlhs, const wchar_t cData);
    //	template<> __declspec(dllimport) bool operator != (CTmplStringBase<wchar_t>& rlhs, const wchar_t* strData);
    //	template<> __declspec(dllimport) bool operator != (CTmplStringBase<wchar_t>& rlhs, const wchar_t cData);
    //#endif
    	typedef CTmplStringBase< char, StrTraits<char> > CStringExA;
    	typedef CTmplStringBase< wchar_t, StrTraits<wchar_t> > CStringExW;
    	typedef CTmplStringBase< TCHAR, StrTraits<TCHAR> > CStringEx;
    //}
    
    //#include "StringExImpl.h"
    //#ifndef STRINGEXIMPL_H
    //#define STRINGEXIMPL_H
    
    //#include "StringEx.h"
    //#	include "UnsafeCast.h"
    
    //namespace Strings
    //{
    	//template<typename T> uint32_t StrTraits<T>::GetLength(const T* strData) const { ASSERT(FALSE); return 0; }
    
    	template<> const char* StrTraits<char>::UINT64_T_IDENTIFIER = "%I64u";
    	template<> const char* StrTraits<char>::INT64_T_IDENTIFIER = "%I64i";
    	template<> const char* StrTraits<char>::LONG_IDENTIFIER = "%li";
    	template<> const wchar_t* StrTraits<wchar_t>::UINT64_T_IDENTIFIER = L"%I64u";
    	template<> const wchar_t* StrTraits<wchar_t>::INT64_T_IDENTIFIER = L"%I64i";
    	template<> const wchar_t* StrTraits<wchar_t>::LONG_IDENTIFIER = L"%li";
    
    	template<> uint32_t StrTraits<char>::GetLength(const char* strData) { return strlen(strData); }
    	template<> uint32_t StrTraits<wchar_t>::GetLength(const wchar_t* strData) { return wcslen(strData); }
    	template<> StrTraits<char>::fnc_tprintf_s* StrTraits<char>::GetFormatFunction(const char*) { return &sprintf_s; }
    	template<> StrTraits<wchar_t>::fnc_tprintf_s* StrTraits<wchar_t>::GetFormatFunction(const wchar_t*) { return &swprintf_s; }
    	template<> StrTraits<char>::fnc_tvprintf_s* StrTraits<char>::GetVFormatFunction(const char*) { return &vsprintf_s; }
    	template<> StrTraits<wchar_t>::fnc_tvprintf_s* StrTraits<wchar_t>::GetVFormatFunction(const wchar_t*) { return &vswprintf_s; }
    	template<> StrTraits<char>::fnc_tvcprintf* StrTraits<char>::GetVFormatCountFunction(const char*) { return &_vscprintf; }
    	template<> StrTraits<wchar_t>::fnc_tvcprintf* StrTraits<wchar_t>::GetVFormatCountFunction(const wchar_t*) { return &_vscwprintf; }
    	template<> StrTraits<char>::fnc_tcscmp* StrTraits<char>::GetCompareFunction(const char*) { return &strcmp; }
    	template<> StrTraits<wchar_t>::fnc_tcscmp* StrTraits<wchar_t>::GetCompareFunction(const wchar_t*) { return &wcscmp; }
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase()
    	{
    		Init();
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(const CTmplStringBase<T, Traits>& rSrc)
    	{
    		Init();
    		*this = rSrc;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(const T* strData)
    	{
    		Init();
    		*this = strData;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(const T cData)
    	{
    		Init();
    		*this = cData;
    	}
    
    #ifdef _MFC_VER
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(const CStringT< T, StrTraitMFC_DLL<T> >& strSrc)
    	{
    		Init();
    		CopyStr(strSrc);
    	}
    #endif
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(uint64_t nData)
    	{
    		Init();
    		*this = nData;
    	}
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(int64_t nData)
    	{
    		Init();
    		*this = nData;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::CTmplStringBase(long nData)
    	{
    		Init();
    		*this = nData;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::~CTmplStringBase()
    	{
    		delete [] m_pData;
    		m_nSize = 0;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (const T* strData)
    	{
    		return Assign(strData);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (const T cData)
    	{
    		return Assign(cData);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (long nData)
    	{
    		return Assign(nData);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (uint64_t nData)
    	{
    		return Assign(nData);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (int64_t nData)
    	{
    		return Assign(nData);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (const CTmplStringBase& rSrc)
    	{
    		CopyStr(rSrc.m_pData);
    		return *this;
    	}
    
    #ifdef _MFC_VER
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::operator = (const CStringT< T, StrTraitMFC_DLL<T> >& rSrc)
    	{
    		return Assign(rSrc);
    	}
    #endif
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, const T* strData)
    	{
    		rlhs.AppendStr(strData);
    		return rlhs;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, const T cData)
    	{
    		rlhs.PrepareBuffer(1);
    		*rlhs.m_pUnusedStart++ = cData;
    		*rlhs.m_pUnusedStart = 0;
    		return rlhs;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, uint64_t nData)
    	{
    		return rlhs.AppendNum(nData, CTmplStringBase<T, Traits>::UINT64_T_IDENTIFIER);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, int64_t nData)
    	{
    		return rlhs.AppendNum(nData, CTmplStringBase<T, Traits>::INT64_T_IDENTIFIER);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>& operator += (CTmplStringBase<T, Traits>& rlhs, long nData)
    	{
    		return rlhs.AppendNum(nData, CTmplStringBase<T, Traits>::LONG_IDENTIFIER);
    	}
    
    	template<typename T, typename Traits> bool operator == (CTmplStringBase<T, Traits>& rlhs, const T* strData)
    	{
    		typename CTmplStringBase<T, Traits>::fnc_tcscmp* Compare = rlhs.GetCompareFunction(strData);
    		return (Compare(rlhs.m_pData, strData) == 0);
    	}
    
    	template<typename T, typename Traits> bool operator == (CTmplStringBase<T, Traits>& rlhs, const T cData)
    	{
    		return (cData == rlhs.m_pData[0]);
    	}
    
    	template<typename T, typename Traits> bool operator != (CTmplStringBase<T, Traits>& rlhs, const T* strData)
    	{
    		return !(rlhs == strData);
    	}
    
    	template<typename T, typename Traits> bool operator != (CTmplStringBase<T, Traits>& rlhs, const T cData)
    	{
    		return !(rlhs == cData);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits>::operator const T* () const
    	{
    		return m_pData;
    	}
    
    	//template<typename T, typename Traits> const T* CTmplStringBase<T, Traits>::GetString() const
    	//{
    	//	return m_pData;
    	//}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::Replace(const CTmplStringBase& strReplaceWhat, const CTmplStringBase& strReplaceWith)
    	{
    		int32_t nNeededSize = ReplaceInternal(strReplaceWhat, strReplaceWith, false);
    		if (nNeededSize > 0) PrepareBuffer(nNeededSize);
    		ReplaceInternal(strReplaceWhat, strReplaceWith, true);
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits> CTmplStringBase<T, Traits>::Right(uint32_t nCount) const
    	{
    		CTmplStringBase<T, Traits> strTemp;
    		unsigned int nSize = ((unsigned int)(m_pUnusedStart - nCount + 1));
    		T* pBuffer = strTemp.GetBuffer(nSize);
    		CopyStrLowLevel(pBuffer, nSize, m_pUnusedStart - nCount, NULL);
    		strTemp.ReleaseBuffer();
    		return strTemp;
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::Delete(uint32_t nStartFrom, uint32_t nCount)
    	{
    		if (nCount == 0)
    		{
    			m_pData[nStartFrom] = 0; 
    			m_pUnusedStart = &m_pData[nStartFrom];
    			return;
    		}
    		unsigned int nBufferSize = (m_pData + m_nSize) - (m_pData + nStartFrom);
    		memmove_s(m_pData + nStartFrom, nBufferSize, m_pData + nStartFrom + nCount, nBufferSize);
    		m_pUnusedStart -= nCount;
    	}
    
    	template<typename T, typename Traits> uint32_t CTmplStringBase<T, Traits>::GetLength() const
    	{
    		return m_pUnusedStart - m_pData;
    	}
    
    	template<typename T, typename Traits> T* CTmplStringBase<T, Traits>::GetBuffer(uint32_t nMinSize)
    	{
    		PrepareBuffer(nMinSize);
    		return m_pData;
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::ReleaseBuffer()
    	{
    		m_pUnusedStart = m_pData + StrTraits<T>::GetLength(m_pData);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::Truncate(uint32_t nNewSize)
    	{
    		m_pData[nNewSize] = 0;
    		m_pUnusedStart = &m_pData[nNewSize];
    	}
    
    	template<typename T, typename Traits> int32_t CTmplStringBase<T, Traits>::Find(const T* strFind, uint32_t nBeginAt) const
    	{
    		const T* pStart = m_pData + nBeginAt;
    		const T* pEnd = m_pData + GetLength();
    		const T* p = pStart;
    		uint32_t nFindLength = StrTraits<T>::GetLength(strFind);
    		while (pStart < pEnd)
    		{
    			if (uint32_t(pEnd - pStart) < nFindLength) return -1;
    			if (*p == *strFind)
    			{
    				bool bMatch = true;
    				for (uint32_t i = 1; i < nFindLength; i++)
    				{
    					if (p[i] != strFind[i])
    					{
    						bMatch = false;
    						break;
    					}
    				}
    				if (bMatch) return (p - m_pData);
    			}
    			p++;
    		}
    		return -1;
    	}
    
    	template<typename T, typename Traits> int32_t CTmplStringBase<T, Traits>::Find(const T cFind, uint32_t nBeginAt) const
    	{
    		CTmplStringBase<T, Traits> strTemp = cFind;
    		return Find(strTemp, nBeginAt);
    	}
    
    	template<typename T, typename Traits> int32_t CTmplStringBase<T, Traits>::ReplaceInternal(const CTmplStringBase& strReplaceWhat, const CTmplStringBase& strReplaceWith, bool bReplace)
    	{
    		const T* m_pDataEnd = m_pUnusedStart;
    		const T* pBufferEnd = m_pData + m_nSize;
    		uint32_t nReplaceWhatSize = StrTraits<T>::GetLength(strReplaceWhat);
    		uint32_t nReplaceWithSize = StrTraits<T>::GetLength(strReplaceWith);
    		int32_t nNeededSize = 0;
    		int32_t nIndex = 0;
    		while ( (nIndex = Find(strReplaceWhat, nIndex)) > -1 )
    		{
    			if (nIndex >= 0)
    			{
    				T* p = m_pData + nIndex;
    				int32_t nAdjustSize = (nReplaceWhatSize - nReplaceWithSize);
    				if (!bReplace)
    				{
    					nNeededSize += nAdjustSize;
    					nIndex++;
    					continue;
    				}
    
    				// Move data so we can copy new data into place:
    				// This is a test --> This is a  test
    				T* pCopyDataStart = p + nReplaceWithSize;
    				unsigned int nDataToCopy = m_pDataEnd - pCopyDataStart;
    				if (nDataToCopy > 0) CopyStrLowLevel(pCopyDataStart, nDataToCopy, pCopyDataStart, NULL);
    
    				// Copy new data into place, overwriting old data with new:
    				// This is a  test --> This is an test
    				// Hint: There is always 0 beyond the end of the data, so out buffer is actually 
    				CopyStrLowLevel(p, pBufferEnd - p, strReplaceWith, NULL);
    			}
    			nIndex++;
    		}
    		if (bReplace)
    			m_pUnusedStart = m_pData + StrTraits<T>::GetLength(m_pData);
    		return nNeededSize;
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::FormatInternal(const T* strFormat, va_list arg)
    	{
    		typename Traits::fnc_tvprintf_s* vformat_s = Traits::GetVFormatFunction(strFormat);
    		typename Traits::fnc_tvcprintf* vformat_count = Traits::GetVFormatCountFunction(strFormat);
    		uint32_t nSizeNeeded = vformat_count(strFormat, arg);
    		uint32_t nUsedSize = GetLength();
    		uint32_t nTotalSize = nUsedSize + nSizeNeeded;
    		PrepareBuffer(nTotalSize);
    		vformat_s(m_pUnusedStart, m_nSize - GetLength(), strFormat, arg);
    		m_pUnusedStart = m_pData + StrTraits<T>::GetLength(m_pData);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::Init()
    	{
    		m_nSize = nDefaultSize;
    		m_pUnusedStart = m_pData = new T[m_nSize];
    		*m_pData = 0;
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::CopyStrLowLevel(T* strDst, uint32_t nDstSize, const T* strSrc, T** pUnusedPtr) const
    	{
    		uint32_t nSize = StrTraits<T>::GetLength(strSrc) + 1;
    		memcpy_s(strDst, nDstSize * sizeof(T), strSrc, nSize * sizeof(T));
    		if (pUnusedPtr) *pUnusedPtr += (nSize - 1);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::CopyStr(const T* strData)
    	{
    		PrepareBuffer( GetLength() + 1 + StrTraits<T>::GetLength(strData) );
    		CopyStrLowLevel(m_pData, m_nSize, strData, &m_pUnusedStart);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::AppendStr(const T* strData)
    	{
    		PrepareBuffer( GetLength() + 1 + StrTraits<T>::GetLength(strData) );
    		CopyStrLowLevel(m_pUnusedStart, m_nSize, strData, &m_pUnusedStart);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::PrepareBuffer(uint32_t nNeededSize)
    	{
    		if (m_nSize - GetLength() < nNeededSize)
    		{
    			uint32_t nNewSize = m_nSize + nNeededSize * 2 + nDefaultSize;
    			T* pTemp = new T[nNewSize];
    			T* pUnusedTemp = pTemp;
    			CopyStrLowLevel(pTemp, nNewSize, m_pData, &pUnusedTemp);
    			this->~CTmplStringBase();
    			m_pData = pTemp;
    			m_nSize = nNewSize;
    			m_pUnusedStart = pUnusedTemp;
    		}
    	}
    
    	template<typename T, typename Traits> template<typename Type> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::Assign(Type& Data)
    	{
    		//m_pUnusedStart = m_pData;
    		Empty();
    		*this += Data;
    		return *this;		
    	}
    
    	template<typename T, typename Traits> template<typename Type> CTmplStringBase<T, Traits>& CTmplStringBase<T, Traits>::AppendNum(Type& Data, const T* strFormat)
    	{
    		T temp[21];
    		typename CTmplStringBase<T, Traits>::fnc_tprintf_s* tprintf_s = GetFormatFunction(temp);
    		tprintf_s(temp, sizeof(temp) / sizeof(T), strFormat, Data);
    		PrepareBuffer( StrTraits<T>::GetLength(temp) );
    		AppendStr(temp);
    		return *this;
    	}
    
    	template<typename T, typename Traits> CTmplStringBase<T, Traits> CTmplStringBase<T, Traits>::Mid(uint32_t nStart, uint32_t nCount) const
    	{
    		CTmplStringBase<T, Traits> strTemp;
    		uint32_t nSize = nCount;
    		if (nSize == 0)
    			nCount = nSize = m_pUnusedStart - (m_pData + nStart);
    		nSize++;
    		T* pBuffer = strTemp.GetBuffer(nSize);
    		memcpy_s(pBuffer, nSize * sizeof(T), m_pData + nStart, nCount * sizeof(T));
    		pBuffer[nSize - 1] = 0;
    		strTemp.ReleaseBuffer();
    		return strTemp;
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::Format(const T* strFormat, ...)
    	{
    		Empty();
    		va_list arg;
    		va_start(arg, strFormat);
    		FormatInternal(strFormat, arg);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::AppendFormat(const T* strFormat, ...)
    	{
    		va_list arg;
    		va_start(arg, strFormat);
    		FormatInternal(strFormat, arg);
    	}
    
    	template<typename T, typename Traits> void CTmplStringBase<T, Traits>::Empty()
    	{
    		m_pUnusedStart = m_pData;
    		*m_pData = 0;
    	}
    }
    
    //#endif // STRINGEXIMPL_H
    #endif // STRINGEX_H

  15. #45
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Quote Originally Posted by phantomotap View Post
    This code... has so very much wrong with it. The code... the concepts... ;_;
    Do enlighten me. Even if just a bit. Every one bit helps.

    You also should probably get a good stingy C++ compiler. Obviously whatever you are using isn't informing you of all the problems that it should be telling you about.
    Such as? Visual Studio compiler has always been helpful with warnings.

    I hope you have a differencing program installed.
    Nope. That I don't.

    But the code compiles! Wonderful!
    I just need to compare the code and see changes were made and why.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Page 3 of 5 FirstFirst 12345 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code Review for upcoming contest
    By Darryl in forum Contests Board
    Replies: 2
    Last Post: 02-28-2006, 02:39 PM
  2. Problem : Threads WILL NOT DIE!!
    By hanhao in forum C++ Programming
    Replies: 2
    Last Post: 04-16-2004, 02:37 PM
  3. True ASM vs. Fake ASM ????
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 04-02-2003, 04:28 AM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 06:06 PM
  5. Replies: 0
    Last Post: 02-21-2002, 06:05 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21