CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Jul 2017
    Posts
    12

    Exclamation Conflicting declaration error

    Hi everyone,

    I am still stuck at using templates inside class. I'm trying to make a BigNumber library in C++ for learning purpose.

    my code is:


    BigInt.h

    Code:
    #include <iostream>
    #include <string>
    
    /**Specifications:
    *   stores number as: intgr for int part and dec for decimal part
    *   member sign is 1 for positive number and -1 for negative and 0 for Not a Number i.e. NaN
    *   Constructor: can take, int, string(formatted as number), float or double
    *   operators to define +, -, *, /, %, power(), <<, >>
    */
    
    namespace GG
    {
    
        class BigInt
        {
        public:
            /** Default constructor */
            BigInt();
    
            template<typename T>
            BigInt(const T&);
    
            /** Default destructor */
            virtual ~BigInt();
    
            /** Copy constructor
            *  \param other Object to copy from
            */
            BigInt(const BigInt& other);
    
            /** Assignment operator
            *  \param other Object to assign from
            *  \return A reference to this
            */
            BigInt& operator=(const BigInt& other);
    
            friend std::ostream& operator<<(std::ostream& os, const BigInt& bigInt);
            friend std::istream& operator>>(std::istream& is, BigInt& bigInt);
    
        protected:
    
        private:
            /**
            *   Number is represented as:
            *   +0.123324 or -0.1232432
            *   +123 or -123 etc
            *   [+ or -] then [numbers] then maybe [.] then [more numbers]
            */
    
            std::string intgr; // Integer part of number i.e. 23 in 23.45
            std::string dec; // decimal part of number i.e. 45 in 23.45
            short sign; // 1 for positive number, -1 for negative and 0 for NaN (Not a Number)
        };
    
        template<typename T>
        BigInt::BigInt(const T& n)
        {
            std::string num_str = std::to_string(n); // |note: previous declaration as ‘std::__cxx11::string num_str’|
            BigInt(num_str); // |error: conflicting declaration ‘GG::BigInt num_str’|
        }
    
    
        //Specialiazed for string
        template<> inline
        BigInt::BigInt<std::string>(const std::string& str)
        {
            BigInt();
        }
    
        //Specialized for char
        template<> inline
        BigInt::BigInt<char>(const char& ch)
        {
            BigInt();
        }
    
    }// namespace GG ends here

    BigInt.cpp
    Code:
    #include "BigInt.h"
    
    #include <string>
    #include <regex>
    
    namespace GG
    {
    
        #define DEBUG_SYMS
        #undef DEBUG_SYMS
    
        BigInt::BigInt()
        {
            //ctor
            dec = "NaN";
            intgr = "NaN";
            sign = 0;
        }
    
    
        BigInt::~BigInt()
        {
            //dtor
        }
    
        BigInt::BigInt(const BigInt& other)
        {
            //copy ctor
        }
    
        BigInt& BigInt::operator=(const BigInt& rhs)
        {
            if (this == &rhs) return *this; // handle self assignment
                                            //assignment operator
            this->intgr = rhs.intgr;
            this->dec = rhs.dec;
            this->sign = rhs.sign;
            return *this;
        }
    
        std::ostream& operator<<(std::ostream& os, const BigInt& bigInt)
        {
            std::string num_str = "";
            if(bigInt.sign == 0)
            {
                os << "NaN";
                return os;
            }
            else if(bigInt.sign == -1)
                num_str = "-";
            num_str += bigInt.intgr;
            if(bigInt.dec != "0")
            {
                num_str += ".";
                num_str += bigInt.dec;
            }
            os << num_str;
    
            return os;
        }
    
        std::istream& operator>>(std::istream& is, BigInt& bigInt)
        {
            std::string input_num;
            is>>input_num;
            bigInt = BigInt(input_num);
            return is;
        }
    
    }// namespace GG ends here

    main.cpp
    Code:
    #include <iostream>
    
    #include "BigInt.h"
    
    using namespace std;
    
    int main()
    {
    
             short short_n = 123;
    	GG::BigInt n(short_n);
    	GG::BigInt n_default;
    	std::cout << n << " " << n_default ;
    	return 0;
    }

    I have written all the code for the sake of completeness so that you could reproduce the problem. But you need to look mainly in BigInt.h in which I am facing problem in specialized string contructor.

    errors are as follows:
    1. ||error: conflicting declaration ‘GG::BigInt num_str’||
    2. ||note: previous declaration as ‘std::__cxx11::string num_str’||

    Please guide me.
    Attached Files Attached Files

  2. #2
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Conflicting declaration error

    Code:
    	template<typename T>
    	BigInt::BigInt(const T& n) : BigInt(to_string(n)) {}
    	/*{
    		std::string num_str = std::to_string(n); // |note: previous declaration as ‘std::__cxx11::string num_str’|
    		BigInt(num_str); // |error: conflicting declaration ‘GG::BigInt num_str’|
    	}*/
    Last edited by 2kaud; July 18th, 2017 at 01:13 PM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Jul 2017
    Posts
    12

    Re: Conflicting declaration error

    Quote Originally Posted by 2kaud View Post
    Code:
    	template<typename T>
    	BigInt::BigInt(const T& n) : BigInt(to_string(n)) {}
    	/*{
    		std::string num_str = std::to_string(n); // |note: previous declaration as ‘std::__cxx11::string num_str’|
    		BigInt(num_str); // |error: conflicting declaration ‘GG::BigInt num_str’|
    	}*/

    Thank you very much, again. It worked.
    Now I am having one more problem that when I pass a C style char array to BigInt() it does not catch the specialized string constructor but it goes to generic constructor, what should I do for this.

    Thanks in advance.

  4. #4
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Conflicting declaration error

    As a c-style array is of type char *, you can't specialise the template because this is of type T&. So you just need a function overload.

    Code:
    BigInt(const char*);
    ...
    BigInt::BigInt(const char* str)
    {
        //Constructor body here
    }
    ...
    GG::BigInt cs("123.456");
    Last edited by 2kaud; July 18th, 2017 at 04:08 PM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5
    Join Date
    Jul 2017
    Posts
    12

    Re: Conflicting declaration error

    Quote Originally Posted by 2kaud View Post
    As a c-style array is of type char *, you can't specialise the template because this is of type T&. So you just need a function overload.

    Code:
    BigInt(const char*);
    ...
    BigInt::BigInt(const char* str)
    {
        //Constructor body here
    }
    ...
    GG::BigInt cs("123.456");
    I have tried this but it is not working. I still get the error:
    1. include/BigInt.h||In instantiation of ‘GG::BigInt::BigInt(const T&) [with T = char [43]]’:|
    include/BigInt.h|65|error: no matching function for call to ‘to_string(const char [43])’|
    Attached Files Attached Files

  6. #6
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Conflicting declaration error

    This compiles with VS2017.

    Code:
    #include <iostream>
    #include <string>
    #include <regex>
    
    /**Specifications:
    *   stores number as: intgr for int part and dec for decimal part
    *   member sign is 1 for positive number and -1 for negative and 0 for Not a Number i.e. NaN
    *   Constructor: can take, int, string(formatted as number), float or double
    *   operators to define +, -, *, /, %, power(), <<, >>
    */
    
    namespace GG
    {
    	//typedef char CP[43];
    
    #define DEBUG_SYMS
    //#undef DEBUG_SYMS
    
    	class BigInt
    	{
    	public:
    		/** Default constructor */
    		BigInt();
    
    		template<typename T>
    		BigInt(const T&);
    
    		template<>
    		BigInt(const std::string& str);
    
    		template<>
    		BigInt(const char& ch);
    
    		BigInt(const char *);
    
    		/** Default destructor */
    		virtual ~BigInt();
    
    		/** Copy constructor
    		*  \param other Object to copy from
    		*/
    		BigInt(const BigInt& other);
    
    		/** Assignment operator
    		*  \param other Object to assign from
    		*  \return A reference to this
    		*/
    		BigInt& operator=(const BigInt& other);
    
    		friend std::ostream& operator<<(std::ostream& os, const BigInt& bigInt);
    		friend std::istream& operator>>(std::istream& is, BigInt& bigInt);
    
    	protected:
    
    	private:
    		/**
    		*   Number is represented as:
    		*   +0.123324 or -0.1232432
    		*   +123 or -123 etc
    		*   [+ or -] then [numbers] then maybe [.] then [more numbers]
    		*/
    
    		std::string intgr; // Integer part of number i.e. 23 in 23.45
    		std::string dec; // decimal part of number i.e. 45 in 23.45
    		short sign; // 1 for positive number, -1 for negative and 0 for NaN (Not a Number)
    	};
    
    	template<typename T>
    	BigInt::BigInt(const T& n) : BigInt(std::to_string(n))
    	{
    		// many many thanks to 2kaud at forums.codeguru.com to make it work
    	}
    
    
    	//Specialiazed for string
    	template<>
    	BigInt::BigInt(const std::string& str)
    	{
    
    #ifdef DEBUG_SYMS
    		std::cout << "string constructor called.\n";
    #endif
    
    		std::string temp = str;
    		for (int i = temp.find('_'); i != -1; i = temp.find('_'))
    		{
    			int j;
    			for (j = 0; temp[i + j] == '_'; ++j);
    			temp = temp.substr(0, i) + temp.substr(i + j);
    		}
    		int last_zero, first_zero;
    
    		std::regex re("([-+]?[0-9]*[.]?[0-9]+)");
    		std::smatch m;
    
    		if (std::regex_match(temp, m, re))
    		{
    
    #ifdef DEBUG_SYMS
    			std::cout << "matched.\n";
    #endif
    
    			if (temp[0] == '-')
    			{
    				sign = -1;
    				temp = temp.substr(1);
    			}
    			else
    			{
    				sign = 1;
    				if (temp[0] == '+')
    					temp = temp.substr(1);
    			}
    			// At this point we have signs removed from the string
    			// now temp has our number but without sign
    			int dec_pos = temp.find('.');
    			if (dec_pos == 0)
    			{
    				intgr = "0";
    				dec = temp.substr(dec_pos);
    
    
    			} //end of if dec_pos == 0
    			else if (dec_pos == -1) // it means we have a simple int
    			{
    				dec = "0";
    				intgr = temp;
    
    			} // end of dec_pos == -1
    
    			else
    			{
    				intgr = temp.substr(0, dec_pos);
    				dec = temp.substr(dec_pos + 1);
    			}
    
    			// Now we are goint to remove if there are any leading zeros
    			// 00000234 becomes 234
    			if (intgr[0] == '0') // execute only if number is like 0000.. not when just 0
    			{
    				first_zero = 0;
    				while (intgr[first_zero] == '0')
    				{
    					++first_zero;
    				}
    				if (intgr[first_zero] != '\0')
    					intgr = intgr.substr(first_zero);
    				else
    					intgr = "0";
    
    			}
    
    			//Now we are going to remove if there are any trailing zeros in decimal part
    			// so 234000000 becomes 234
    			last_zero = dec.length() - 1;
    			while (dec[last_zero] == '0' && last_zero > 0)
    				--last_zero;
    			dec = dec.substr(0, last_zero + 1);
    
    			// At last check for negative zero
    			if (intgr == "0" && dec == "0")
    				sign = 1;
    
    		} // end of if regex match
    
    		else
    		{
    			sign = 0;
    			intgr = dec = "NaN";
    		}
    	}// speciliazed template for string ends here
    
    
    	 //Specialized for char
    	template<>
    	BigInt::BigInt(const char& ch) : BigInt(std::string(1, ch))
    	{
    
    	}
    
    	//Specialized template for char*
    	BigInt::BigInt(const char *arr)
    	{
    		std::cout << "char * constructor called" << std::endl;
    	}
    
    	//    BigInt::BigInt(const char arr[])
    	//    {
    	//        std::cout<<"char [] constructor called"<<std::endl;
    	//    }
    }// namespace GG ends here
    
    
    namespace GG
    {
    
    #define DEBUG_SYMS
    #undef DEBUG_SYMS
    
    	BigInt::BigInt()
    	{
    		//ctor
    		dec = "NaN";
    		intgr = "NaN";
    		sign = 0;
    	}
    
    	//    BigInt::BigInt(const long& n)
    	//    {
    	//        dec = "0"; // since long can't have decimal points
    	//        sign = (n>=0)?1:-1;
    	//        intgr = (n>=0)?std::to_string(n):std::to_string(n).substr(1);
    	//    }
    	//
    	//    BigInt::BigInt(const long long& n)
    	//    {
    	//        dec = "0"; // since long can't have decimal points
    	//        sign = (n>=0)?1:-1;
    	//        intgr = (n>=0)?std::to_string(n):std::to_string(n).substr(1);
    	//    }
    	//
    	//    BigInt::BigInt(const int& n)
    	//    {
    	//        dec = "0"; // since long can't have decimal points
    	//        sign = (n>=0)?1:-1;
    	//        intgr = (n>=0)?std::to_string(n):std::to_string(n).substr(1);
    	//    }
    	//
    	//    BigInt::BigInt(const float& n)
    	//    {
    	//        std::string str = std::to_string(n);
    	//        sign = (n>=0)?1:-1;
    	//        if(n<0)
    	//            str = str.substr(1);
    	//        size_t dec_pos = str.find('.');
    	//        intgr = str.substr(0, dec_pos);
    	//        dec = str.substr(dec_pos + 1);
    	//        // remove trailing zeros in decimal part i.e. make 000000 as 0 and make 123000 as 123
    	//        int last_zero = dec.length() - 1;
    	//        while(dec[last_zero] == '0' && last_zero > 0)
    	//            --last_zero;
    	//        dec = dec.substr(0, last_zero + 1);
    	//
    	//    }
    	//
    	//    BigInt::BigInt(const double& n)
    	//    {
    	//        std::string str = std::to_string(n);
    	//        sign = (n>=0)?1:-1;
    	//        if(n<0)
    	//            str = str.substr(1);
    	//        size_t dec_pos = str.find('.');
    	//        intgr = str.substr(0, dec_pos);
    	//        dec = str.substr(dec_pos + 1);
    	//        // remove trailing zeros in decimal part i.e. make 000000 as 0 and make 123000 as 123
    	//        int last_zero = dec.length() - 1;
    	//        while(dec[last_zero] == '0' && last_zero > 0)
    	//            --last_zero;
    	//        dec = dec.substr(0, last_zero + 1);
    	//    }
    	//
    	//    BigInt::BigInt(const long double& n)
    	//    {
    	//        std::string str = std::to_string(n);
    	//        sign = (n>=0)?1:-1;
    	//        if(n<0)
    	//            str = str.substr(1);
    	//        size_t dec_pos = str.find('.');
    	//        intgr = str.substr(0, dec_pos);
    	//        dec = str.substr(dec_pos + 1);
    	//        // remove trailing zeros in decimal part i.e. make 000000 as 0 and make 123000 as 123
    	//        int last_zero = dec.length() - 1;
    	//        while(dec[last_zero] == '0' && last_zero > 0)
    	//            --last_zero;
    	//        dec = dec.substr(0, last_zero + 1);
    	//    }
    	//
    	//    BigInt::BigInt(const std::string& str)
    	//    {
    	//        #ifdef DEBUG_SYMS
    	//            std::cout<<"string constructor called.\n";
    	//        #endif
    	//
    	//        std::string temp = str;
    	//        for( int i = temp.find('_'); i!= -1; i=temp.find('_'))
    	//        {
    	//            int j;
    	//            for( j = 0; temp[i+j]=='_'; ++j);
    	//            temp = temp.substr(0, i) + temp.substr(i+j);
    	//        }
    	//        int last_zero, first_zero;
    	//
    	//        std::regex re("([-+]?[0-9]*[.]?[0-9]+)");
    	//        std::smatch m;
    	//
    	//        if (std::regex_match(temp, m, re))
    	//        {
    	//            #ifdef DEBUG_SYMS
    	//                std::cout<<"matched.\n";
    	//            #endif
    	//            if(temp[0] == '-')
    	//            {
    	//                sign = -1;
    	//                temp = temp.substr(1);
    	//            }
    	//            else
    	//            {
    	//                sign = 1;
    	//                if(temp[0] == '+')
    	//                    temp = temp.substr(1);
    	//            }
    	//            // At this point we have signs removed from the string
    	//            // now temp has our number but without sign
    	//            int dec_pos = temp.find('.');
    	//            if(dec_pos == 0)
    	//            {
    	//                intgr = "0";
    	//                dec = temp.substr(dec_pos);
    	//
    	//
    	//            } //end of if dec_pos == 0
    	//            else if(dec_pos == -1) // it means we have a simple int
    	//            {
    	//                dec = "0";
    	//                intgr = temp;
    	//
    	//            } // end of dec_pos == -1
    	//
    	//            else
    	//            {
    	//                intgr = temp.substr(0, dec_pos);
    	//                dec = temp.substr(dec_pos + 1);
    	//            }
    	//
    	//            // Now we are goint to remove if there are any leading zeros
    	//            // 00000234 becomes 234
    	//            if(intgr[0] == '0') // execute only if number is like 0000.. not when just 0
    	//            {
    	//                first_zero = 0;
    	//                while(intgr[first_zero] == '0')
    	//                {
    	//                    ++first_zero;
    	//                }
    	//                if(intgr[first_zero] != '\0')
    	//                    intgr = intgr.substr(first_zero);
    	//                else
    	//                    intgr = "0";
    	//
    	//            }
    	//
    	//            //Now we are going to remove if there are any trailing zeros in decimal part
    	//            // so 234000000 becomes 234
    	//            last_zero = dec.length() - 1;
    	//            while(dec[last_zero] == '0' && last_zero > 0)
    	//                --last_zero;
    	//            dec = dec.substr(0, last_zero + 1);
    	//
    	//            // At last check for negative zero
    	//            if( intgr == "0" && dec == "0")
    	//                sign = 1;
    	//
    	//        } // end of if regex match
    	//
    	//        else
    	//        {
    	//            sign = 0;
    	//            intgr = dec = "NaN";
    	//        }
    	//    }
    	//
    	//    BigInt::BigInt(const char& ch)
    	//    {
    	//        if(ch >='0' && ch<='9')
    	//        {
    	//            intgr = std::string(1, ch);
    	//            dec = "0";
    	//            sign = 1;
    	//        }
    	//        else
    	//        {
    	//            intgr = dec = "NaN";
    	//            sign = 0;
    	//        }
    	//    }
    
    	BigInt::~BigInt()
    	{
    		//dtor
    	}
    
    	BigInt::BigInt(const BigInt& other)
    	{
    		//copy ctor
    	}
    
    	BigInt& BigInt::operator=(const BigInt& rhs)
    	{
    		if (this == &rhs) return *this; // handle self assignment
    										//assignment operator
    		this->intgr = rhs.intgr;
    		this->dec = rhs.dec;
    		this->sign = rhs.sign;
    		return *this;
    	}
    
    	std::ostream& operator<<(std::ostream& os, const BigInt& bigInt)
    	{
    		std::string num_str = "";
    		if (bigInt.sign == 0)
    		{
    			os << "NaN";
    			return os;
    		}
    		else if (bigInt.sign == -1)
    			num_str = "-";
    		num_str += bigInt.intgr;
    		if (bigInt.dec != "0")
    		{
    			num_str += ".";
    			num_str += bigInt.dec;
    		}
    		os << num_str;
    
    		return os;
    	}
    
    	std::istream& operator>>(std::istream& is, BigInt& bigInt)
    	{
    		std::string input_num;
    		is >> input_num;
    		bigInt = BigInt(input_num);
    		return is;
    	}
    
    }// namespace GG ends here
    
    
    int main()
    {
    	using namespace std::string_literals;
    	char arr[] = "_-____20__999_______343_453_100_000_00____";
    
    	short short_n = 123;
    	GG::BigInt n(short_n);
    	GG::BigInt n_default;
    	GG::BigInt str_n('1');
    	GG::BigInt strstr("123"s);
    	GG::BigInt char_arr_n(arr);
    	std::cout << n << " " << n_default << " " << str_n << " " << char_arr_n << std::endl;
    
    	GG::BigInt input;
    	std::cout << "Input a number: ";
    	std::cin >> input;
    	std::cout << input;
    	return 0;
    }
    When run, displays
    Code:
    string constructor called.
    matched.
    string constructor called.
    matched.
    string constructor called.
    matched.
    char * constructor called
    123 NaN 1 NaN
    Input a number:
    as I defined DEBUG_SYMS

    PS There's no need to attribute me in the code.
    Last edited by 2kaud; July 19th, 2017 at 03:55 AM. Reason: PS
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    Jul 2017
    Posts
    12

    Re: Conflicting declaration error

    Quote Originally Posted by 2kaud View Post
    This compiles with VS2017.

    Code:
    #include <iostream>
    #include <string>
    #include <regex>
    
    /**Specifications:
    *   stores number as: intgr for int part and dec for decimal part
    *   member sign is 1 for positive number and -1 for negative and 0 for Not a Number i.e. NaN
    *   Constructor: can take, int, string(formatted as number), float or double
    *   operators to define +, -, *, /, %, power(), <<, >>
    */
    
    namespace GG
    {
    	//typedef char CP[43];
    
    #define DEBUG_SYMS
    //#undef DEBUG_SYMS
    
    	class BigInt
    	{
    	public:
    		/** Default constructor */
    		BigInt();
    
    		template<typename T>
    		BigInt(const T&);
    
    		template<>
    		BigInt(const std::string& str);
    
    		template<>
    		BigInt(const char& ch);
    
    		BigInt(const char *);
    
    		/** Default destructor */
    		virtual ~BigInt();
    
    		/** Copy constructor
    		*  \param other Object to copy from
    		*/
    		BigInt(const BigInt& other);
    
    		/** Assignment operator
    		*  \param other Object to assign from
    		*  \return A reference to this
    		*/
    		BigInt& operator=(const BigInt& other);
    
    		friend std::ostream& operator<<(std::ostream& os, const BigInt& bigInt);
    		friend std::istream& operator>>(std::istream& is, BigInt& bigInt);
    
    	protected:
    
    	private:
    		/**
    		*   Number is represented as:
    		*   +0.123324 or -0.1232432
    		*   +123 or -123 etc
    		*   [+ or -] then [numbers] then maybe [.] then [more numbers]
    		*/
    
    		std::string intgr; // Integer part of number i.e. 23 in 23.45
    		std::string dec; // decimal part of number i.e. 45 in 23.45
    		short sign; // 1 for positive number, -1 for negative and 0 for NaN (Not a Number)
    	};
    
    	template<typename T>
    	BigInt::BigInt(const T& n) : BigInt(std::to_string(n))
    	{
    		// many many thanks to 2kaud at forums.codeguru.com to make it work
    	}
    
    
    	//Specialiazed for string
    	template<>
    	BigInt::BigInt(const std::string& str)
    	{
    
    #ifdef DEBUG_SYMS
    		std::cout << "string constructor called.\n";
    #endif
    
    		std::string temp = str;
    		for (int i = temp.find('_'); i != -1; i = temp.find('_'))
    		{
    			int j;
    			for (j = 0; temp[i + j] == '_'; ++j);
    			temp = temp.substr(0, i) + temp.substr(i + j);
    		}
    		int last_zero, first_zero;
    
    		std::regex re("([-+]?[0-9]*[.]?[0-9]+)");
    		std::smatch m;
    
    		if (std::regex_match(temp, m, re))
    		{
    
    #ifdef DEBUG_SYMS
    			std::cout << "matched.\n";
    #endif
    
    			if (temp[0] == '-')
    			{
    				sign = -1;
    				temp = temp.substr(1);
    			}
    			else
    			{
    				sign = 1;
    				if (temp[0] == '+')
    					temp = temp.substr(1);
    			}
    			// At this point we have signs removed from the string
    			// now temp has our number but without sign
    			int dec_pos = temp.find('.');
    			if (dec_pos == 0)
    			{
    				intgr = "0";
    				dec = temp.substr(dec_pos);
    
    
    			} //end of if dec_pos == 0
    			else if (dec_pos == -1) // it means we have a simple int
    			{
    				dec = "0";
    				intgr = temp;
    
    			} // end of dec_pos == -1
    
    			else
    			{
    				intgr = temp.substr(0, dec_pos);
    				dec = temp.substr(dec_pos + 1);
    			}
    
    			// Now we are goint to remove if there are any leading zeros
    			// 00000234 becomes 234
    			if (intgr[0] == '0') // execute only if number is like 0000.. not when just 0
    			{
    				first_zero = 0;
    				while (intgr[first_zero] == '0')
    				{
    					++first_zero;
    				}
    				if (intgr[first_zero] != '\0')
    					intgr = intgr.substr(first_zero);
    				else
    					intgr = "0";
    
    			}
    
    			//Now we are going to remove if there are any trailing zeros in decimal part
    			// so 234000000 becomes 234
    			last_zero = dec.length() - 1;
    			while (dec[last_zero] == '0' && last_zero > 0)
    				--last_zero;
    			dec = dec.substr(0, last_zero + 1);
    
    			// At last check for negative zero
    			if (intgr == "0" && dec == "0")
    				sign = 1;
    
    		} // end of if regex match
    
    		else
    		{
    			sign = 0;
    			intgr = dec = "NaN";
    		}
    	}// speciliazed template for string ends here
    
    
    	 //Specialized for char
    	template<>
    	BigInt::BigInt(const char& ch) : BigInt(std::string(1, ch))
    	{
    
    	}
    
    	//Specialized template for char*
    	BigInt::BigInt(const char *arr)
    	{
    		std::cout << "char * constructor called" << std::endl;
    	}
    
    	//    BigInt::BigInt(const char arr[])
    	//    {
    	//        std::cout<<"char [] constructor called"<<std::endl;
    	//    }
    }// namespace GG ends here
    
    
    namespace GG
    {
    
    #define DEBUG_SYMS
    #undef DEBUG_SYMS
    
    	BigInt::BigInt()
    	{
    		//ctor
    		dec = "NaN";
    		intgr = "NaN";
    		sign = 0;
    	}
    
    	//    BigInt::BigInt(const long& n)
    	//    {
    	//        dec = "0"; // since long can't have decimal points
    	//        sign = (n>=0)?1:-1;
    	//        intgr = (n>=0)?std::to_string(n):std::to_string(n).substr(1);
    	//    }
    	//
    	//    BigInt::BigInt(const long long& n)
    	//    {
    	//        dec = "0"; // since long can't have decimal points
    	//        sign = (n>=0)?1:-1;
    	//        intgr = (n>=0)?std::to_string(n):std::to_string(n).substr(1);
    	//    }
    	//
    	//    BigInt::BigInt(const int& n)
    	//    {
    	//        dec = "0"; // since long can't have decimal points
    	//        sign = (n>=0)?1:-1;
    	//        intgr = (n>=0)?std::to_string(n):std::to_string(n).substr(1);
    	//    }
    	//
    	//    BigInt::BigInt(const float& n)
    	//    {
    	//        std::string str = std::to_string(n);
    	//        sign = (n>=0)?1:-1;
    	//        if(n<0)
    	//            str = str.substr(1);
    	//        size_t dec_pos = str.find('.');
    	//        intgr = str.substr(0, dec_pos);
    	//        dec = str.substr(dec_pos + 1);
    	//        // remove trailing zeros in decimal part i.e. make 000000 as 0 and make 123000 as 123
    	//        int last_zero = dec.length() - 1;
    	//        while(dec[last_zero] == '0' && last_zero > 0)
    	//            --last_zero;
    	//        dec = dec.substr(0, last_zero + 1);
    	//
    	//    }
    	//
    	//    BigInt::BigInt(const double& n)
    	//    {
    	//        std::string str = std::to_string(n);
    	//        sign = (n>=0)?1:-1;
    	//        if(n<0)
    	//            str = str.substr(1);
    	//        size_t dec_pos = str.find('.');
    	//        intgr = str.substr(0, dec_pos);
    	//        dec = str.substr(dec_pos + 1);
    	//        // remove trailing zeros in decimal part i.e. make 000000 as 0 and make 123000 as 123
    	//        int last_zero = dec.length() - 1;
    	//        while(dec[last_zero] == '0' && last_zero > 0)
    	//            --last_zero;
    	//        dec = dec.substr(0, last_zero + 1);
    	//    }
    	//
    	//    BigInt::BigInt(const long double& n)
    	//    {
    	//        std::string str = std::to_string(n);
    	//        sign = (n>=0)?1:-1;
    	//        if(n<0)
    	//            str = str.substr(1);
    	//        size_t dec_pos = str.find('.');
    	//        intgr = str.substr(0, dec_pos);
    	//        dec = str.substr(dec_pos + 1);
    	//        // remove trailing zeros in decimal part i.e. make 000000 as 0 and make 123000 as 123
    	//        int last_zero = dec.length() - 1;
    	//        while(dec[last_zero] == '0' && last_zero > 0)
    	//            --last_zero;
    	//        dec = dec.substr(0, last_zero + 1);
    	//    }
    	//
    	//    BigInt::BigInt(const std::string& str)
    	//    {
    	//        #ifdef DEBUG_SYMS
    	//            std::cout<<"string constructor called.\n";
    	//        #endif
    	//
    	//        std::string temp = str;
    	//        for( int i = temp.find('_'); i!= -1; i=temp.find('_'))
    	//        {
    	//            int j;
    	//            for( j = 0; temp[i+j]=='_'; ++j);
    	//            temp = temp.substr(0, i) + temp.substr(i+j);
    	//        }
    	//        int last_zero, first_zero;
    	//
    	//        std::regex re("([-+]?[0-9]*[.]?[0-9]+)");
    	//        std::smatch m;
    	//
    	//        if (std::regex_match(temp, m, re))
    	//        {
    	//            #ifdef DEBUG_SYMS
    	//                std::cout<<"matched.\n";
    	//            #endif
    	//            if(temp[0] == '-')
    	//            {
    	//                sign = -1;
    	//                temp = temp.substr(1);
    	//            }
    	//            else
    	//            {
    	//                sign = 1;
    	//                if(temp[0] == '+')
    	//                    temp = temp.substr(1);
    	//            }
    	//            // At this point we have signs removed from the string
    	//            // now temp has our number but without sign
    	//            int dec_pos = temp.find('.');
    	//            if(dec_pos == 0)
    	//            {
    	//                intgr = "0";
    	//                dec = temp.substr(dec_pos);
    	//
    	//
    	//            } //end of if dec_pos == 0
    	//            else if(dec_pos == -1) // it means we have a simple int
    	//            {
    	//                dec = "0";
    	//                intgr = temp;
    	//
    	//            } // end of dec_pos == -1
    	//
    	//            else
    	//            {
    	//                intgr = temp.substr(0, dec_pos);
    	//                dec = temp.substr(dec_pos + 1);
    	//            }
    	//
    	//            // Now we are goint to remove if there are any leading zeros
    	//            // 00000234 becomes 234
    	//            if(intgr[0] == '0') // execute only if number is like 0000.. not when just 0
    	//            {
    	//                first_zero = 0;
    	//                while(intgr[first_zero] == '0')
    	//                {
    	//                    ++first_zero;
    	//                }
    	//                if(intgr[first_zero] != '\0')
    	//                    intgr = intgr.substr(first_zero);
    	//                else
    	//                    intgr = "0";
    	//
    	//            }
    	//
    	//            //Now we are going to remove if there are any trailing zeros in decimal part
    	//            // so 234000000 becomes 234
    	//            last_zero = dec.length() - 1;
    	//            while(dec[last_zero] == '0' && last_zero > 0)
    	//                --last_zero;
    	//            dec = dec.substr(0, last_zero + 1);
    	//
    	//            // At last check for negative zero
    	//            if( intgr == "0" && dec == "0")
    	//                sign = 1;
    	//
    	//        } // end of if regex match
    	//
    	//        else
    	//        {
    	//            sign = 0;
    	//            intgr = dec = "NaN";
    	//        }
    	//    }
    	//
    	//    BigInt::BigInt(const char& ch)
    	//    {
    	//        if(ch >='0' && ch<='9')
    	//        {
    	//            intgr = std::string(1, ch);
    	//            dec = "0";
    	//            sign = 1;
    	//        }
    	//        else
    	//        {
    	//            intgr = dec = "NaN";
    	//            sign = 0;
    	//        }
    	//    }
    
    	BigInt::~BigInt()
    	{
    		//dtor
    	}
    
    	BigInt::BigInt(const BigInt& other)
    	{
    		//copy ctor
    	}
    
    	BigInt& BigInt::operator=(const BigInt& rhs)
    	{
    		if (this == &rhs) return *this; // handle self assignment
    										//assignment operator
    		this->intgr = rhs.intgr;
    		this->dec = rhs.dec;
    		this->sign = rhs.sign;
    		return *this;
    	}
    
    	std::ostream& operator<<(std::ostream& os, const BigInt& bigInt)
    	{
    		std::string num_str = "";
    		if (bigInt.sign == 0)
    		{
    			os << "NaN";
    			return os;
    		}
    		else if (bigInt.sign == -1)
    			num_str = "-";
    		num_str += bigInt.intgr;
    		if (bigInt.dec != "0")
    		{
    			num_str += ".";
    			num_str += bigInt.dec;
    		}
    		os << num_str;
    
    		return os;
    	}
    
    	std::istream& operator>>(std::istream& is, BigInt& bigInt)
    	{
    		std::string input_num;
    		is >> input_num;
    		bigInt = BigInt(input_num);
    		return is;
    	}
    
    }// namespace GG ends here
    
    
    int main()
    {
    	using namespace std::string_literals;
    	char arr[] = "_-____20__999_______343_453_100_000_00____";
    
    	short short_n = 123;
    	GG::BigInt n(short_n);
    	GG::BigInt n_default;
    	GG::BigInt str_n('1');
    	GG::BigInt strstr("123"s);
    	GG::BigInt char_arr_n(arr);
    	std::cout << n << " " << n_default << " " << str_n << " " << char_arr_n << std::endl;
    
    	GG::BigInt input;
    	std::cout << "Input a number: ";
    	std::cin >> input;
    	std::cout << input;
    	return 0;
    }
    When run, displays
    Code:
    string constructor called.
    matched.
    string constructor called.
    matched.
    string constructor called.
    matched.
    char * constructor called
    123 NaN 1 NaN
    Input a number:
    as I defined DEBUG_SYMS

    PS There's no need to attribute me in the code.
    Ohk so there is some problem with GCC I suppose. I have updated it to latest version but still, it is not compiling.
    About your name, actually I forgot to delete it while sharing the files here, I deleted everything in the code I pasted directly into question but I forgot to prepare different files to upload and just uploaded the original ones on which I am working.

  8. #8
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Conflicting declaration error

    Ohk so there is some problem with GCC
    Sorry, but I use only VS. Can any guru who does use GCC advise?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  9. #9
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Conflicting declaration error

    you cannot specialize a member template inside class body ( VS allows but it's not standard ).
    Regarding your original problem, it's better to use overloading instead, somthing like:

    Code:
    class BigInt
    {
    public:
    	BigInt();
    	explicit BigInt( char );
    	explicit BigInt( const char* );
    	explicit BigInt( std::string const& );
    
    	template<int N>
    	explicit BigInt(char (&arr)[N]); // this will take string literals BigInt("123")
    
    	template<typename T>
    	explicit BigInt( T const& );
    ....

  10. #10
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Conflicting declaration error

    you cannot specialize a member template inside class body ( VS allows but it's not standard ).
    then it should be!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  11. #11
    Join Date
    Jul 2017
    Posts
    12

    Thumbs up Re: Conflicting declaration error

    Quote Originally Posted by superbonzo View Post
    you cannot specialize a member template inside class body ( VS allows but it's not standard ).
    Regarding your original problem, it's better to use overloading instead, somthing like:

    Code:
    class BigInt
    {
    public:
    	BigInt();
    	explicit BigInt( char );
    	explicit BigInt( const char* );
    	explicit BigInt( std::string const& );
    
    	template<int N>
    	explicit BigInt(char (&arr)[N]); // this will take string literals BigInt("123")
    
    	template<typename T>
    	explicit BigInt( T const& );
    ....
    Thank you very much for the clarification.
    But after making everything explicit I will not be able to do things like,
    Code:
    BigInt a = 1;
    or
    Code:
    std::string str = "123";
    BigInt a = str;
    So, I guess it is better to specify that you can not use an array to initialize its object, instead of losing so much convenience.

    BTW, thank you again.

  12. #12
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Conflicting declaration error

    Quote Originally Posted by JohnnyTest View Post
    So, I guess it is better to specify that you can not use an array to initialize its object, instead of losing so much convenience.
    you don't need "explicit" for the array constructor, I added it just for correctness sake. Note that the more implicit converting constructors you add the higher the chances of getting unwanted/unexpected results. This is even more true when mixing converting constructors taking primitive types ( chars, ints, ... ) because you have to deal with the language implicit conversion/promotion rules ...

    so, in real world big int libraries, implicit conversions are minimized in favour of explicit constructors and factory functions.
    Moreover, you typically don't want unconstrained template constructors ( eg. BigInt( T const& ) ), these should be constrained via SFINAE to avoid troubles like the one you got in and to allow some extendability ...

  13. #13
    Join Date
    Jul 2017
    Posts
    12

    Re: Conflicting declaration error

    Quote Originally Posted by superbonzo View Post
    in real world big int libraries, implicit conversions are minimized in favour of explicit constructors and factory functions.
    I didn't know that. Then it's okay.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured