f



Is there any difference of g++ 3.4.3 and g++ 3.3.4 ?

HI, my source code was compiled ok in g++ 3.3.4 . But when I try to
use 3.4.3 to compile, I get the following error:


Utility.h: In constructor `Buffer<size>::Buffer(const char*)':
Utility.h:174: error: `buffer' undeclared (first use this function)
Utility.h:174: error: (Each undeclared identifier is reported only
once for each function it appears in.)
Utility.h:176: error: no matching function for call to `strchr(<type
error>, char)'
/usr/include/iso/string_iso.h:130: note: candidates are: char* strchr
(const char*, int)
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/
3.4.3/cstring:107: note:                 char* std::strchr(char*, int)
Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
(const char*)':
Utility.h:183: error: `buffer' undeclared (first use this function)
Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
(char)':
Utility.h:258: error: `buffer' undeclared (first use this function)
Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
(int)':
Utility.h:271: error: `buffer' undeclared (first use this function)
Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
(long int)':
Utility.h:287: error: `buffer' undeclared (first use this function)
Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
(short int)':
Utility.h:303: error: `buffer' undeclared (first use this function)
Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
(double)':
Utility.h:319: error: `buffer' undeclared (first use this function)
Utility.h: In member function `int Buffer<size>::length()':
Utility.h:329: error: `buffer' undeclared (first use this function)


I've checked the source code, look like "buffer" is declared at the
very beginning, can you help to suggest were is the problem? And what
is the hint of checking this problem?

Here is the source code:


#ifndef _Utility_h
#define _Utility_h

extern "C" {
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
}

// quick and dirty template string class (unfortunately non-standard!)

template<int size>
class String {
public:
    char buffer[size + 1];

    String() { buffer[0] = '\0';}

    String(const char *from) {
//        strncpy(buffer, from, size);
	int smaller = (size < strlen(from)) ? size : strlen(from);
        strncpy(buffer, from, smaller);
        buffer[smaller] = '\0';
    }

    String(const int from) {
        memset(buffer, '\0', size);
        sprintf(buffer, "%d", from);
    }

    // assignment from String<size>

    String& operator=(const String& from) {
	int smaller = (size < from.getSize())? size : from.getSize();
	strncpy(buffer, from.buffer, smaller);
	buffer[smaller] = '\0';
        return *this;
    }


    // assignment from const char *

    String& operator=(const char *from) {
//        strncpy(buffer, from, size);
	if (!from) {
	    buffer[0] = '\0';
	    return *this;
	}
	int smaller = (size < strlen(from)) ? size : strlen(from);
        strncpy(buffer, from, smaller);
	buffer[smaller] = '\0';
        return *this;
    }

    // assignment from int&

    String& operator=(const int& from) {
        memset(buffer, '\0', size);
        sprintf(buffer, "%d", from);
        return *this;
    }


    // assignment from short&

    String& operator=(const short& from) {
        memset(buffer, '\0', size);
        sprintf(buffer, "%d", from);
        return *this;
    }

    // assignment from long&

    String& operator=(const long& from) {
        memset(buffer, '\0', size);
        sprintf(buffer, "%d", from);
        return *this;
    }

    // assignment from double&

    String& operator=(const double& from) {
        memset(buffer, '\0', size);
        sprintf(buffer, "%f", from);
        return *this;
    }

    // comparison to String<size>&

    int operator==(const String& to) const {
		// JK 990329 - Compare null-terminated string rather than
		//             whole block of memory
        // return !memcmp(buffer, to.buffer, size);
        return !strncmp(buffer, to.buffer, size);
    }

    // comparison to String<size>&

    int operator!=(const String& to) const {
		// JK 990329 - Compare null-terminated string rather than
		//             whole block of memory
        // return memcmp(buffer, to.buffer, size) != 0;
        return strncmp(buffer, to.buffer, size) != 0;
    }

    // comparison to const char *

    int operator==(const char *to) const {
        return !strcmp(buffer, to);
    }

    // comparison to const char *

    int operator!=(const char *to) const {
        return strcmp(buffer, to);
    }

//    operator const char*() const { return buffer; }

    operator char *() const { return (char *)buffer; }

    operator int() const { return atoi(buffer); }

    char *operator*() const { return (char *)buffer; }

    int getSize() const{ return size; }
};

// Buffer is used only for generating the ISQL output.

template<int size>
class Buffer : public String<size> {
    char *end;
public:
    Buffer(const char *from = "") {
        strncpy(buffer, from, size);
        buffer[size] = '\0';
        end = strchr(buffer, '\0');
    }

    // append operator from const char *

    Buffer& operator+(const char *from) {
        int length = strlen(from);
        if (end + length <= buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, buffer + size - end);
            end = buffer + size;
        }
        return *this;
    }

    Buffer& operator+=(const char *from) {
        int length = strlen(from);
        if (end + length <= String<size>::buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, String<size>::buffer + size - end);
            end = String<size>::buffer + size;
        }
        return *this;
    }

    // append operator from char

    Buffer& operator+=(char from) {
        if (from == '\0') {
            return *this;
        }
        if (end + 1 <= String<size>::buffer + size) {
            end[0] = from;
            end += 1;
        }
        return *this;
    }

    // append operator from int

    Buffer& operator+=(int i) {
        char from[16];
        sprintf(from, "%d", i);
        int length = strlen(from);
        if (end + length <= String<size>::buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, String<size>::buffer + size - end);
            end = String<size>::buffer + size;
        }
        return *this;
    }

    // append operator from double

    Buffer& operator+=(double d) {
        char from[64];
		// JK 990329 - Ouput precision to 9 decimal places
        // sprintf(from, "%f", d);
        sprintf(from, "%.9f", d);
        int length = strlen(from);
        if (end + length <= String<size>::buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, String<size>::buffer + size - end);
            end = String<size>::buffer + size;
        }
        return *this;
    }

    // append operator from char

    Buffer& operator+(char from) {
        if (from == '\0') {
            return *this;
        }
        if (end + 1 <= buffer + size) {
            end[0] = from;
            end += 1;
        }
        return *this;
    }

    // append operator from int

    Buffer& operator+(int i) {
        char from[16];
        sprintf(from, "%d", i);
        int length = strlen(from);
        if (end + length <= buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, buffer + size - end);
            end = buffer + size;
        }
        return *this;
    }

    // append operator from long

    Buffer& operator+(long i) {
        char from[16];
        sprintf(from, "%d", i);
        int length = strlen(from);
        if (end + length <= buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, buffer + size - end);
            end = buffer + size;
        }
        return *this;
    }

    // append operator from short

    Buffer& operator+(short i) {
        char from[16];
        sprintf(from, "%d", i);
        int length = strlen(from);
        if (end + length <= buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, buffer + size - end);
            end = buffer + size;
        }
        return *this;
    }

    // append operator from double

    Buffer& operator+(double d) {
        char from[64];
        sprintf(from, "%.9f", d);
        int length = strlen(from);
        if (end + length <= buffer + size) {
            memcpy(end, from, length);
            end += length;
        } else {
            memcpy(end, from, buffer + size - end);
            end = buffer + size;
        }
        return *this;
    }

    int length() { return end - buffer; }

};

class Date : public String<16> {
    static Date time;
public:
    Date& operator=(const Date& from) {
        String<16>::operator=(from);
        return *this;
    }

    // TODO check that it is fine to leave this out
    //    Date& operator=(const char *& from) {
    //    String<16>::operator=(from);
    //    return *this;
    //}

    Date& operator=(const char *from) {
        String<16>::operator=(from);
        return *this;
    }

    int operator>(const Date& to) const {
        return memcmp(buffer, to.buffer, 16) > 0;
    }

    int operator>=(const Date& to) const {
        return memcmp(buffer, to.buffer, 16) >= 0;
    }

    int operator<(const Date& to) const {
        return memcmp(buffer, to.buffer, 16) < 0;
    }

    int operator<=(const Date& to) const {
        return memcmp(buffer, to.buffer, 16) <= 0;
    }

    int validate() const {
        int yr, mo, dy, hr, mn, sc, hn;

        if (sscanf(buffer, "%4d%2d%2d%2d%2d%2d%2d",
            &yr, &mo, &dy, &hr, &mn, &sc, &hn) != 7) {
            return -1;
        }
        if (yr < 1995 || mo < 1 || mo > 12 || dy < 1 || dy > 31 || hr
< 0 ||
            hr > 23 || mn < 0 || mn > 60 || sc < 0 || sc > 60) {
            return -1;
        }
        return 1;
    }
    static const Date& currentTime();
};

#endif /* _Utility_h */
0
carfield (39)
6/30/2009 11:45:29 AM
comp.lang.c++ 49423 articles. 7 followers. Post Follow

3 Replies
1051 Views

Similar Articles

[PageSpeed] 23

Carfield Yim wrote:
> HI, my source code was compiled ok in g++ 3.3.4 . But when I try to
> use 3.4.3 to compile, I get the following error:
> 
> 
> Utility.h: In constructor `Buffer<size>::Buffer(const char*)':
> Utility.h:174: error: `buffer' undeclared (first use this function)
> Utility.h:174: error: (Each undeclared identifier is reported only
> once for each function it appears in.)
> Utility.h:176: error: no matching function for call to `strchr(<type
> error>, char)'
> /usr/include/iso/string_iso.h:130: note: candidates are: char* strchr
> (const char*, int)
> /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/
> 3.4.3/cstring:107: note:                 char* std::strchr(char*, int)
> Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
> (const char*)':
> Utility.h:183: error: `buffer' undeclared (first use this function)
> Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
> (char)':
> Utility.h:258: error: `buffer' undeclared (first use this function)
> Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
> (int)':
> Utility.h:271: error: `buffer' undeclared (first use this function)
> Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
> (long int)':
> Utility.h:287: error: `buffer' undeclared (first use this function)
> Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
> (short int)':
> Utility.h:303: error: `buffer' undeclared (first use this function)
> Utility.h: In member function `Buffer<size>& Buffer<size>::operator+
> (double)':
> Utility.h:319: error: `buffer' undeclared (first use this function)
> Utility.h: In member function `int Buffer<size>::length()':
> Utility.h:329: error: `buffer' undeclared (first use this function)
> 
> 
> I've checked the source code, look like "buffer" is declared at the
> very beginning, can you help to suggest were is the problem? And what
> is the hint of checking this problem?
> 

Read the FAQ about how to post requests for help. Nobody here wants to 
read through three-hundred fifty lines of mostly irrelevant code. Start 
cutting things out that don't pertain to the problem. Reduce the code to 
a minimal example that still has the problem. If you haven't figured out 
what's wrong from doing that, post the minimal example.

Two quick tips, though (probably not relevant to this particular problem):

> #ifndef _Utility_h
> #define _Utility_h
> 

Names that begin with an underscore followed by a capital letter are 
reserved to the implementation. Don't use them.

> extern "C" {
> #include <string.h>
> #include <stdlib.h>
> #include <stdio.h>
> }

Don't ever do this. #include directives for standard headers must be at 
global scope (in particular, outside any namespace directives and 
outside any extern "C" or extern "C++" blocks). That's also a good 
policy for any other #include directives.

-- 
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)
0
pete2666 (1733)
6/30/2009 12:00:40 PM
Carfield Yim wrote:

> HI, my source code was compiled ok in g++ 3.3.4 . But when I try to
> use 3.4.3 to compile, I get the following error:
> 
> 
> Utility.h: In constructor `Buffer<size>::Buffer(const char*)':
> Utility.h:174: error: `buffer' undeclared (first use this function)
<snip> 
> 
> I've checked the source code, look like "buffer" is declared at the
> very beginning, can you help to suggest were is the problem? And what
> is the hint of checking this problem?

The problem is in the so-called 'two phase name lookup' that is used 
when compiling templates. g++ 3.3.4 gets this wrong and g++ 3.4.3 gets 
it right.

> 
> Here is the source code:
> 
> 
> #ifndef _Utility_h
> #define _Utility_h
> 
> extern "C" {
> #include <string.h>
> #include <stdlib.h>
> #include <stdio.h>
> }
> 
> // quick and dirty template string class (unfortunately non-standard!)
> 
> template<int size>
> class String {
> public:
>     char buffer[size + 1];
<snip>
> };
> 
> // Buffer is used only for generating the ISQL output.
> 
> template<int size>
> class Buffer : public String<size> {
>     char *end;
> public:
>     Buffer(const char *from = "") {
>         strncpy(buffer, from, size);

There are two times that a compiler performs name lookup for names that 
occur within a template:
1. When the template code is parsed by the compiler
2. When the template is instantiated

The first time, the compiler tries to resolve all the names that are 
apparently not dependent on any of the template parameters. This 
includes the name 'buffer'. However, because the base class itself 
depends on a template parameter, it is excluded from the search (because 
the compiler can't be sure that there will not be a later specialisation 
with completely different members).

That is the reason why the compiler is unable to resolve the name 
'buffer' to something meaningful.

At the second lookup, all the remaining (dependent) names are resolved 
and, because it is known which instantiation of the base class to use, 
the base class is also included in the search.
The trick is now to let it be known that 'buffer' is actually a 
dependent name and should be looked up in the second phase. This can be 
done by explicitly using the member-access notation: this->buffer.

<snip>

Bart v Ingen Schenau
-- 
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

0
bart855 (270)
6/30/2009 6:05:42 PM
>
> The problem is in the so-called 'two phase name lookup' that is used
> when compiling templates. g++ 3.3.4 gets this wrong and g++ 3.4.3 gets
> it right.
>
>
>
>
>
>
>
> > Here is the source code:
>
> > #ifndef _Utility_h
> > #define _Utility_h
>
> > extern "C" {
> > #include <string.h>
> > #include <stdlib.h>
> > #include <stdio.h>
> > }
>
> > // quick and dirty template string class (unfortunately non-standard!)
>
> > template<int size>
> > class String {
> > public:
> > =A0 =A0 char buffer[size + 1];
> <snip>
> > };
>
> > // Buffer is used only for generating the ISQL output.
>
> > template<int size>
> > class Buffer : public String<size> {
> > =A0 =A0 char *end;
> > public:
> > =A0 =A0 Buffer(const char *from =3D "") {
> > =A0 =A0 =A0 =A0 strncpy(buffer, from, size);
>
> There are two times that a compiler performs name lookup for names that
> occur within a template:
> 1. When the template code is parsed by the compiler
> 2. When the template is instantiated
>
> The first time, the compiler tries to resolve all the names that are
> apparently not dependent on any of the template parameters. This
> includes the name 'buffer'. However, because the base class itself
> depends on a template parameter, it is excluded from the search (because
> the compiler can't be sure that there will not be a later specialisation
> with completely different members).
>
> That is the reason why the compiler is unable to resolve the name
> 'buffer' to something meaningful.
>
> At the second lookup, all the remaining (dependent) names are resolved
> and, because it is known which instantiation of the base class to use,
> the base class is also included in the search.
> The trick is now to let it be known that 'buffer' is actually a
> dependent name and should be looked up in the second phase. This can be
> done by explicitly using the member-access notation: this->buffer.
>
Thanks a lot
0
carfield (39)
7/2/2009 11:52:08 AM
Reply: