hash_map
hash_map
hash_map
is an SGI extention instead of C++
standard. So this should not be under the std::. Do you know this?
(see section Definition)
stl_config.h:# define __STL_BEGIN_NAMESPACE namespace std
{
O, std::hash_map<Key, Data, HashFcn, EqualKey, Alloc> Yamauchi Hitoshi 2003-5-7(Wed), revised 2004-11-10(Wed) Oh, hash_map, why you are not in standard? You are not in standard but your namespace is standard. Map is so important, it is a basic data structure. java.util.HashMap is so nice. But why are you like you are? Once I saw your source, the hash< char* > is amazing. Using you is as difficult as writing you. Your template error always confuses me. ``Error! instanciate here..'' with 10 lines messages, but I can't see what's happen. Maybe I should change the #include <hash_map> to #include <map>. It helps me a little but only a little.
Just that!
--- Marvin (The Hitchhiker's guide to the galaxy)
Why do you use hash_map?
--- J.H.
LessThan Comparable means there is operator<() available. And partial ordering is OK. Strict Weak Ordering is more strict than this condition. Total ordering is more strict than Strict Weak Ordering.
/** vector< LTCtype > V; // LTC ... Less than comparable. ... sort(V.begin(), V.end(), less_LTC()); */ struct less_LTC : public std::binary_function< LTCtype, LTCtype, bool > { bool operator()(const LTCtype& x, const LTCtype& y) { return((x.d_index) < (y.d_index)); // just an example } };
class BSElem { public: BSElem(int i) : d_index(i) {}; public: int d_index; }; std::vector< BSElem > v; ... std::sort(v.begin(), v.end(), less_LTC()); ... BSElem tolookup(i); std::binary_search(v.begin(), v.end(), tolookup, less_LTC())) ? "found" : "not found";
list< int > alist; for(int i = 0; i < 4; i++){ alist.push_back(i); }You can compile:
for(list< int >::const_iterator ii = alist.begin(); ii != alist.end(); ++ii){ cout << *ii << " "; }But, you cannot compile:
for(list< int >::const_reverse_iterator ii = alist.rbegin(); ii != alist.rend(); ++ii){ cout << *ii << " "; }because of next compilation error (in the case of gcc).
riter.cc:71: error: no match for 'operator!=' in 'ri != std::list<_Tp, _Alloc>::rend() [with _Tp = int, _Alloc = std::allocatorThis is surprising, isn't it? Just I change the iterator -> reverse_iterator, begin() -> rbegin(), and end() -> rend(). The reason is so complicated. One is const and non-const does not need the same type by ANSI C++ standard. This means,]()'
int a = 3; if (a == 4){} // This line can be error since a is non const and 4 is const.
But I think this error may not happend. But, STL implementation, the rbegin() and rend() is iterator's template class and (forward) iterator is not. So, this is really not comparable. Other problem is also in the compiler's assumption of which constructor should be chosen. The rbegin() is copy constructed to const_reverse_iterator, so alist.rbegin() can know it should be const. But what can rend() should be? If alist is not const. The overload of returning value only does not work in C++, e.g., overloading int f() and double f() are not permitted. So, rend() here just return the non-const version, since alist is non-const.
To tell (or trick) this to the compiler, you can cast to const, but DO NOT call constructor, since it copy's the whole list and you want to make an iterator of the copy of the list. So, cast to reference to the const version. Then,
for(list< int >::const_reverse_iterator ii = alist.rbegin(); ii != ((const list< int >& )alist).rend(); ++ii){ cout << *ii << " "; }
it works! But, hey, please C++.
Namespace function is usually logical grouping of the names. But it is also an identifier of the space.
Java has a nice convention which can give you an unique namespace. This
is great. Like in my case, de.mpg.mpi-sb.ag4.yhitoshi
could
give me almost unique name on the Internet. Moreover, java's class name
and filename correspondence support this uniqueness. Both uniqueness and
logcal grouping are here.
However, C++ has totally lost the uniqueness. You can make any namespace which has the same name but different groups. Almost everyone in graphics make own Math namespace and inside this namespace Vector and Matrix are there. Oh my.
To make this uniqueness worser, C++ has a function to make namespace alias. Which is in C++ programming language 3rd Edition section 8.2.7, after the section 8.2.5 Avoiding name clashes.
namespace MPII {} // is short and may clash. namespace MaxPlanckInstituteFuerInformatik {} // is long. namespace MPII = MaxPlanckInstituteFuerInformatik {} // alias like this.
One thing C++ book said is you can use like symbolic link. You have several version namespace, and just choose one.
namespace MaxPlanckInstitute_GMU_v1_0_0 {} // version 1.0.0 namespace MaxPlanckInstitute_GMU_v1_1_0 {} // version 1.1.0 namespace MaxPlanckInstitute_GMU_v1_2_0 {} // version 1.2.0 namespace MPII = MaxPlanckInstitute_GMU_v1_2_0 {} // use 1.2.0 by alias
Yes. This is somehow make sense. But I think this is too complicated. And the last line of the C++ book's this section is:
On the other hand, overuse of aliases (of any kind) can lead to confusion.
There is somehow nice idea of anonymous name like lambda
in Lisp. If you use a name only once, why you need make a name with
being afraid about name clash. But this Unname namespace is I do not
know whether it is really useful or not (but I would rather say no).
Unnamed namespace is not extern
, so usage is in one
file. We have already static
. If you will clash a name in
one file, I will rather make two files and make them static. The example
of Unnamed name space in C++ book is:
// in FileA.cc namespace { int a; void f(){ /* implementation I using a. */ } int g(){ /* implementation I using a. */ } } namespace { int a; void f(){ /* implementation II using a. */ } int g(){ /* implementation II using a. */ } }
But I will use other name in one file. Or, change the name of external linkage necessary part and keep rest static.
One thing is not so beautiful in C++ is namespace, class, struct, and union are not the same. They all have a slightly different way (e.g., `;' is necessary with class, struct, union, but not namespace.) Yet nested class and struct are possible. In Java, they are the same and you do not need to remember small difference. However, I think many of them come from historical reason and performance issue.
Unnamed class and struct may more useful like lambda
, I
presume. In Java, you can use with abstract class. But I do not need it
in C++ since it is already quite complicated and I will be happy to give
one time name for this. Thanks. There is also unnamed union and it is
another function.... Sigh.
Once I saw next code when I moved gcc 4.
class A { ... friend void f(){ access to private of A; } };
gcc 3.x, you can call the function f(), like ::f(); However, gcc 4.1.0 said,
friend.cc:**: error: '::f' has not been declared
I can not call that f() if I tried several ways like
extern void f(); class A { ... friend void f(){ access to private of A; } };
// f() is not declared class A { ... friend void f(); // useless (in 11.5.1 C++ book) }; void f(){ // if you did not access to inside of A, since this f() is not a // friend of A } void bar(){ ... f(); // you can call f(); }Now C++ magic, you can write
// f() is not declared class A { ... friend void f() { // definition of f()! } };I think it is legal, but you have just made a function you can not call it at all!.
I do not know exactly the reason of this one. But I can assume this feature of C++. It may be a historical reason.
extern void g(); // ::g(); namespace A { extern void g(); // A::g(); } namespace A { class B { friend void g(); // should be A::g(); } }If g() is not found, where does the f() live? Natural answer may be in the declared scope. But it is the same to the member. Howvere, it that is the member, friend does not so much make sense. (member scope, but not the member function. static do that. (By the way, in this sense, don't you feel the static member function a bit horrible?))
One more tip,
// f() is not declared class A { ... friend void ::f() { // lives in global? // definition of f()! } };does not work in gcc 4.1.0. But friend is declaration keyword. So, it smells dangerous to use this way. It is better to not tweak the language. ``Kunshi ayauki ni Chikayorazu. (=Der Weise begibt sich nicht in Gefahr.)
proj +---+ lib_dir_a: a_0.o, a_1.o | (symbols: sa_0, sa_1, Undef sb_0, lib_dir_a.a) + lib_dir_b: b_0.o, b_1.o (symbols: sb_0, sb_1, Undef sa_0, lib_dir_b.a)Now making a lib
ar cr lib_proj.a lib_dir_a.a lib_dir_b.a
,
sa_0's definition is there, but still undefined one remains. Also do
ar cr lib_proj.a lib_dir_b.a lib_dir_a.a
, this
time sb_0 becomes both defined and undefined entries.
class BaseA { public: virtual void func(); }; class DerivedB : public BaseA { public: void func(); // this is virtual }; class DerivedC : public DerivedC { public: void func(); // is this virtual? // since DerivedB's func() has no virtual keyword };The DerivedC::func is also virtual. The reason I recommend to add virtual to all func() is, when the all the class are some how large, you see the void func() line, and you know it is virtual or not. So, inline virtual only optimized the method is exactly specified like DerivedC::func(), but this is not so useful. `final' is one missing piece in current standard C++.