By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,221 Members | 1,663 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,221 IT Pros & Developers. It's quick & easy.

Compiling with g++ 3.0

P: n/a
The following code works with g++ 2.75 but
i've some troubles with compiling with g++ 3.0.

Thanks in advance if you have a solution.

Here is the error message.

main.hpp:28: specializing `struct std::hash<std::string>' in different
namespace
/usr/include/g++-v3/ext/stl_hash_fun.h:68: from definition of `template<class
_Key> struct std::hash'
make: *** [resource_identifier.lo] Error 1
#include <pair.h>
#include <string>
#include <map>
#include <vector>
#ifdef __GNUC__ /* grabbed in libstdc++ faq */
#if __GNUC__ < 3
#include <hash_map.h>
namespace Sgi { using ::hash_map; }; // inherit globals
#else
#include <ext/hash_map>
#if __GNUC_MINOR__ == 0
namespace Sgi = std; // GCC 3.0
#else
namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later
#endif
#endif
#else // ... there are other compilers, right?
namespace Sgi = std;
#endif
using namespace std;
//TODO: include this definition in the Hashtable class
template<> struct hash<string>
{
size_t operator()(const string& s) const
{
return hash<char const*>()(s.c_str());
}
};
#ifdef NAMESPACES
namespace foobar {
#endif

class NoSuchElementException
{
public:
NoSuchElementException(string w) {_what = w;}
virtual ~NoSuchElementException() {}
virtual string what() { return _what; }
private:
string _what;
};
template <class T> class Hashtable //: public ost::Conditional
{
public:
Hashtable() {} //: Conditional() {}

virtual ~Hashtable() {clear(); }
virtual T put(const string& key, T value)
{
assert(key.c_str() != NULL); //TODO: must throw ?

// enterMutex();
T returnValue = mHashtable[key];
mHashtable[key] = value;
// leaveMutex();

return returnValue;
}

virtual T get(const string& key) throw (NoSuchElementException)
{
assert(key.c_str() != NULL); //TODO: must throw ?
// enterMutex();

if (mHashtable.empty())
{
// leaveMutex ();
throw NoSuchElementException (key);
}

if (mHashtable.find(key) == mHashtable.end())
{
// leaveMutex();
throw NoSuchElementException(key);
}

T returnValue = mHashtable[key];
//leaveMutex();

return returnValue;
}
virtual void del(const string& key) throw (NoSuchElementException)
{
assert(key.c_str() != NULL); //TODO: must throw ?
// enterMutex();

if (mHashtable.find(key) == mHashtable.end()) {
// leaveMutex();
throw NoSuchElementException(key);
}
mHashtable.erase (key);
// leaveMutex();

return;
}
virtual void clear() {
// enterMutex();
mHashtable.erase(mHashtable.begin(), mHashtable.end());
// leaveMutex();
}

virtual bool isEmpty () {
bool ret;
// enterMutex();
ret = mHashtable.empty ();
// leaveMutex();
return ret;
}

virtual vector<pair<string,T> > toVector()
throw (NoSuchElementException)
{
vector <pair<string, T> > v;
// enterMutex();

if (mHashtable.empty()) {
// leaveMutex();
throw NoSuchElementException(string("hashtable is empty"));
}

for(hash_map<string, T , hash<string> >::iterator iter
= mHashtable.begin(); iter != mHashtable.end(); ++iter)
{
pair <string, T> p(*iter);// (iter->first, iter->second);
v.insert(v.begin(), p);
}

//leaveMutex();
return v;
}

protected:
hash_map<string, T, hash<string> > mHashtable;
};

int
main(void)
{
Hashtable<int> h;

return 0;
}
#ifdef NAMESPACES
}; // foobar
#endif

/** EMACS **
* Local variables:
* mode: c++
* c-basic-offset: 4
* End:
*/

Here is my release of g++ 3.0:
$ g++-3.0 -v
Reading specs from /usr/lib/gcc-lib/i386-linux/3.0.4/specs
Configured with: ../src/configure -v
--enable-languages=c,c++,java,f77,proto,objc
--prefix=/usr --infodir=/share/info --mandir=/share/mx
Thread model: posix
gcc version 3.0.4

Here is my release of g++ 2.95:
g++ -v
Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.4/specs
gcc version 2.95.4 20011002 (Debian prerelease)

--
Lu*********@cvf.fr

Jul 22 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
Luc Mazardo wrote:
The following code works with g++ 2.75 but
i've some troubles with compiling with g++ 3.0.

Thanks in advance if you have a solution.

Here is the error message.

main.hpp:28: specializing `struct std::hash<std::string>' in different
namespace
/usr/include/g++-v3/ext/stl_hash_fun.h:68: from definition of `template<class
_Key> struct std::hash'
make: *** [resource_identifier.lo] Error 1
hash_map is not part of STL and so the gcc team ( in an effort to be
standards compliant) moved the hash* templates into the __gnu_cxx
namespace. The gcc 3.x series is also more standards compliant and so
you'll need to fix some gcc 2.9x things.


#include <pair.h> ^^^^^^^^ don't need this header - std::pair is found in std::map and
pair.h is non-standard #include <string>
#include <map>
#include <vector>
#ifdef __GNUC__ /* grabbed in libstdc++ faq */
#if __GNUC__ < 3
#include <hash_map.h>
namespace Sgi { using ::hash_map; }; // inherit globals
#else
#include <ext/hash_map>
#if __GNUC_MINOR__ == 0
namespace Sgi = std; // GCC 3.0
#else
namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later
#endif
#endif
#else // ... there are other compilers, right?
namespace Sgi = std;
#endif
using namespace std;
using namespace __gnu_cxx;


//TODO: include this definition in the Hashtable class namespace __gnu_cxx
{
template<> struct hash<string>
{
size_t operator()(const string& s) const
{
return hash<char const*>()(s.c_str());
}
};
};


#ifdef NAMESPACES
namespace foobar {
#endif

class NoSuchElementException
{
public:
NoSuchElementException(string w) {_what = w;}
virtual ~NoSuchElementException() {}
virtual string what() { return _what; }
private:
string _what;
};
template <class T> class Hashtable //: public ost::Conditional
{
public:
Hashtable() {} //: Conditional() {}

virtual ~Hashtable() {clear(); }
virtual T put(const string& key, T value)
{
assert(key.c_str() != NULL); //TODO: must throw ?

// enterMutex();
T returnValue = mHashtable[key];
mHashtable[key] = value;
// leaveMutex();

return returnValue;
}

virtual T get(const string& key) throw (NoSuchElementException)
{
assert(key.c_str() != NULL); //TODO: must throw ?
// enterMutex();

if (mHashtable.empty())
{
// leaveMutex ();
throw NoSuchElementException (key);
}

if (mHashtable.find(key) == mHashtable.end())
{
// leaveMutex();
throw NoSuchElementException(key);
}

T returnValue = mHashtable[key];
//leaveMutex();

return returnValue;
}
virtual void del(const string& key) throw (NoSuchElementException)
{
assert(key.c_str() != NULL); //TODO: must throw ?
// enterMutex();

if (mHashtable.find(key) == mHashtable.end()) {
// leaveMutex();
throw NoSuchElementException(key);
}
mHashtable.erase (key);
// leaveMutex();

return;
}
virtual void clear() {
// enterMutex();
mHashtable.erase(mHashtable.begin(), mHashtable.end());
// leaveMutex();
}

virtual bool isEmpty () {
bool ret;
// enterMutex();
ret = mHashtable.empty ();
// leaveMutex();
return ret;
}

virtual vector<pair<string,T> > toVector()
throw (NoSuchElementException)
{
vector <pair<string, T> > v;
// enterMutex();

if (mHashtable.empty()) {
// leaveMutex();
throw NoSuchElementException(string("hashtable is empty"));
}

for(hash_map<string, T , hash<string> >::iterator iter
Need to use typename - like this:

for(typename hash_map<string, T , hash<string> >::iterator iter
= mHashtable.begin(); iter != mHashtable.end(); ++iter)
{
pair <string, T> p(*iter);// (iter->first, iter->second);
v.insert(v.begin(), p);
}

//leaveMutex();
return v;
}

protected:
hash_map<string, T, hash<string> > mHashtable;
};

int
main(void)
{
Hashtable<int> h;

return 0;
}
#ifdef NAMESPACES
}; // foobar
#endif

/** EMACS **
* Local variables:
* mode: c++
* c-basic-offset: 4
* End:
*/

Jul 22 '05 #2

P: n/a
In article <bu*******@dispatch.concentric.net>, Gianni Mariani wrote:
Luc Mazardo wrote:

#include <pair.h>

^^^^^^^^ don't need this header - std::pair is found in std::map and
pair.h is non-standard


For someone who wants to use pair and doesn't need map/multimap, the
<utility> header. This header just defines std::pair and std::relops

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 22 '05 #3

P: n/a
In article <m0************@beepbeep.dev33.cvf>, Luc Mazardo wrote:
assert(key.c_str() != NULL); //TODO: must throw ?


This is a silly test. If s is a string, s.c_str() is never NULL,
because that function is guaranteed to return a valid '\0'-terminated
c string.

Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 22 '05 #4

P: n/a
> Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.
Every non-private method should be virtual.
Donovan Rebbechi wrote:
In article <m0************@beepbeep.dev33.cvf>, Luc Mazardo wrote:
assert(key.c_str() != NULL); //TODO: must throw ?


This is a silly test. If s is a string, s.c_str() is never NULL,
because that function is guaranteed to return a valid '\0'-terminated
c string.

Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/


--
Bret Pehrson
mailto:br**@infowest.com
NOSPAM - Include this key in all e-mail correspondence <<38952rglkwdsl>>
Jul 22 '05 #5

P: n/a
Donovan Rebbechi wrote:
In article <bu*******@dispatch.concentric.net>, Gianni Mariani wrote:
Luc Mazardo wrote:
#include <pair.h>


^^^^^^^^ don't need this header - std::pair is found in std::map and
pair.h is non-standard


gcc 3.4 (pre-release) reports it as a "non standard" header.



For someone who wants to use pair and doesn't need map/multimap, the
<utility> header. This header just defines std::pair and std::relops
That would be nice - I think the way to do this is to #include <utility>

Cheers,


... same

Jul 22 '05 #6

P: n/a
Bret Pehrson wrote:
Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.

Every non-private method should be virtual.


I disagree. Consider the case where you have to do some common
startup/cleanup around a virtual function. I'd actually make the
virtual as a protected. See below. I'd argue that you don't want to
make Base::f() a virtual.

class Base
{
private:
void setup();
void cleanup();
protected:
virtual void do_work();
public:
void f()
{
setup();
do_work();
cleanup();
}

// other methods redacted
};
Jul 22 '05 #7

P: n/a
In article <40***************@infowest.com>, Bret Pehrson wrote:
Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.


Every non-private method should be virtual.


That's another way of saying that every class (or at least every
container class) should be designed for extension via public inheritance.
What's your basis for this belief ? Or, if I've mischaracterised your
opinion, what is it about the hash map that makes it a better candidate
for subclassing than other classes, or other container classes ?

Note that the standard container classes do not use virtual methods. Why
not ? In your opinion, did the standards committee simply get it wrong ?

Since it is in your opinion advantageous to make these containers
subclassable, could you provide some good examples of useful derived classes ?

On to the problems of making methods virtual:

How do you write a "virtual" assignment operator ?

For example, what does this code do ?

HashBase h1;
HashDerived h2;

h1 = h2;

The problem is that you can treat a class like a "value" or a "reference".
"value" classes can be assigned to. Classes that are handled via reference
may be copyable, but you can't treat them as (assignable) values. You need
to wrap them in a "handle"/"envelope"/"pimpl" class to do that. Which adds
indirection.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 22 '05 #8

P: n/a
Bret Pehrson wrote:
Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.


Every non-private method should be virtual.


Heh, I've seen people write that every virtual function should be
private, and that makes more sense than what you write.
Anyway, may I ask what the reason for your above statement is?

Jul 22 '05 #9

P: n/a
On Thu, 22 Jan 2004 19:44:41 GMT in comp.lang.c++, red floyd
<no*****@here.dude> was alleged to have written:
I disagree. Consider the case where you have to do some common
startup/cleanup around a virtual function. I'd actually make the
virtual as a protected.


If that is your reason, you should make the virtual function private.
You don't want subclasses calling it without the common startup/cleanup
any more than you want foreigners to do so.

Jul 22 '05 #10

P: n/a
On Thu, 22 Jan 2004 23:07:42 +0100, Rolf Magnus <ra******@t-online.de>
wrote:
Bret Pehrson wrote:
Is there a reason why you're declaring all of those virtual member
functions ? It seems inappropriate for this class.


Every non-private method should be virtual.


Heh, I've seen people write that every virtual function should be
private, and that makes more sense than what you write.
Anyway, may I ask what the reason for your above statement is?


He has to be a troll, surely?

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #11

P: n/a
> The problem with virtual functions is that people can
override them in derived classes.
"Problem"??? The **OPTION** to override is the *whole* point.
Now sometimes this is a
good thing because people can specialize the behaviour for
the subclass in hand. Unfortunately they can also warp the
behaviour such that the overridden function does something
totally different from the original behaviour.
True, but at least they have the *OPTION* to do that. Don't protect me from
myself.
The more you refuse to fix a classes hierarchies behaviour
by making the functions virtual the more scope you allow for
the above mistake to occur. By making the entire behaviour
of your class hierarchy fluid the less confidence you have
that the subclasses are indeed homogenous.


As a class designer, it isn't my problem if the derivatives are misused -- that
is the class user's problem.

--
Bret Pehrson
mailto:br**@infowest.com
NOSPAM - Include this key in all e-mail correspondence <<38952rglkwdsl>>
Jul 22 '05 #12

P: n/a
Bret Pehrson wrote:
I'd be interested to hear why a virtual function should be private.
To be able to check for pre- and post conditions in the base class
wihout the derived classes needing to call any extra functions. Didn't
you ever get into a situation where your derived class's virtual
function absolutely _needs_ to call the one from the base class or
another member function of it for your code to work? Better let the
base class always handle it, by doing something like:

class Base
{
public:
void foo(int x); // x _must_ always lower than 100
private:
virtual void do_foo(int x) = 0;
};

void Base::foo(int x)
{
if (x>=100) throw std::range_error();
do_foo(x);
}

class Derived : public Base
{
private:
void do_foo(int x);
};

void Derived::do_foo(int x)
{
// no need to care for range here
}

do_foo is private because it's not supposed to be called directly.
A real world example for post conditions could be a window object that
gets events, and those events must propagate up the inheritance
hierarchy. Instead of letting the one who derived remember calling the
base class's function, you already care for that in the base class.
And some people say that the above should always be done so that you can
(also later if needed e.g. for a bug fix) easily add pre- and post
condition check in the base class without the need to change all the
classes derived from it, which might actually be out of your control if
you're implementing a library or a plugin framework.
Let me expand a little: every (non-template) class that isn't
expressly not intended for derivation should by default have all
non-private methods declared virtual.
I wonder why you exclude templates.
How many times have you used a class outside of your direct source
manipulation control (library or otherwise) that didn't have one or
more virtual methods,
but that was suitable for derivation?
Actually not very often, but it did indeed happen. But to my experience,
it was obvious that those functions should have been made virtual in
the base class. There are most often other functions that obviously
don't need to be virtual.
Let's discuss the hacks that must be used to attempt to overcome this
in code...


I really didn't have to deal that much with it to get a knowledge about
those :-)

Jul 22 '05 #13

P: n/a


Bret Pehrson wrote:


True, but at least they have the *OPTION* to do that. Don't protect me from
myself.

Its not a question about protecting you from yourself. Its a question
of protecting those that come after you.

The more you refuse to fix a classes hierarchies behaviour
by making the functions virtual the more scope you allow for
the above mistake to occur. By making the entire behaviour
of your class hierarchy fluid the less confidence you have
that the subclasses are indeed homogenous.

As a class designer, it isn't my problem if the derivatives are misused -- that
is the class user's problem.


By making everything virtual you haven't designed a class. What you have
done is provide a namespace for a bunch of function to reside in. Your
class has no predictable behaviour it is simply an interface (which in
some cases is fine). You are in effect saying that there is nothing
concrete that defines what this class is, and what you end up with is
either a blamanche or java.

Jul 22 '05 #14

P: n/a
> Its a question of protecting those that come after you.

That is equivalent as protecting me from myself; or more generally, protecting
someone from themself.
You are in effect saying that there is nothing
concrete that defines what this class is, and what you end up with is
either a blamanche or java.
You make it sound like these classes are just arbitrarily floating around in
nether-space, and by pure happenstance create something.

The base class is well defined. The derived class(es) is(are) well defined.
What isn't defined?

I don't know what "blamanche" is.
lilburne wrote:
Bret Pehrson wrote:


True, but at least they have the *OPTION* to do that. Don't protect me from
myself.


Its not a question about protecting you from yourself. Its a question
of protecting those that come after you.
The more you refuse to fix a classes hierarchies behaviour
by making the functions virtual the more scope you allow for
the above mistake to occur. By making the entire behaviour
of your class hierarchy fluid the less confidence you have
that the subclasses are indeed homogenous.

As a class designer, it isn't my problem if the derivatives are misused -- that
is the class user's problem.


By making everything virtual you haven't designed a class. What you have
done is provide a namespace for a bunch of function to reside in. Your
class has no predictable behaviour it is simply an interface (which in
some cases is fine). You are in effect saying that there is nothing
concrete that defines what this class is, and what you end up with is
either a blamanche or java.


--
Bret Pehrson
mailto:br**@infowest.com
NOSPAM - Include this key in all e-mail correspondence <<38952rglkwdsl>>
Jul 22 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.