Vector.h

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #if !defined(_Vector_h_)
00032 #define _Vector_h_
00033 
00034 #if !defined (cap_use_pdvector)
00035 #include <vector>
00036 #include <algorithm>
00037 #include <functional>
00038 
00039 #define pdvector std::vector
00040 #define VECTOR_SORT(l1, f)    std::sort(l1.begin(), l1.end(), ptr_fun(f));
00041 //  Note on erase:  in STL, the end_pos iterator points to one element beyond the desired
00042 //  erasure range, thus we increment it here.
00043 #define VECTOR_ERASE(v, start_pos, end_pos) v.erase(v.begin() + start_pos, v.begin() + (end_pos + 1))
00044 #define VECTOR_APPEND(v1, v2) v1.insert(v1.end(), v2.begin(), v2.end())
00045 #define GET_ITER(v, pos) (v.begin() + pos)
00046 
00047 #else
00048 
00049 #if defined(external_templates)
00050 #pragma interface
00051 #endif
00052 
00053 #include "common/h/language.h"
00054 
00055 #if defined(os_windows)
00056 //turn off 255 char identifier truncation message
00057 #pragma warning (disable: 4786)
00058 #endif
00059 
00060 #define VECTOR_APPEND(l1, l2)   { for (unsigned int _i=0; _i < (l2).size(); _i++) (l1).push_back((l2)[_i]); }
00061 #define VECTOR_SORT(l1, f)  l1.sort((qsort_cmpfunc_t)f);
00062 #define VECTOR_ERASE(v, start_pos, end_pos) v.erase(start_pos, end_pos)
00063 #define GET_ITER(v, pos) v.getIter(pos)
00064 
00065 
00066 #ifdef _KERNEL
00067 #include <sys/types.h>
00068 #include <sys/kmem.h>
00069 #include <sys/debug.h> // ASSERT()
00070 #define assert ASSERT
00071 #else
00072 #include <assert.h>
00073 #include <stdlib.h>
00074 #include <stdio.h>
00075 #include <sys/types.h>
00076 #endif
00077 
00078 extern "C" {
00079    typedef int (*qsort_cmpfunc_t)(const void *, const void *);
00080 }
00081 
00082 #ifndef _KERNEL
00083 #include <new> // placement (void*) new to coax copy-ctor
00084 #elif defined(_LP64)
00085 inline void *operator new(unsigned long /* size_t */, void *place) { 
00086    return place; 
00087 }
00088 #else
00089 inline void *operator new(unsigned /* size_t does not work */, void *place) { 
00090    return place; 
00091 }
00092 #endif
00093 
00094 #ifndef NULL
00095 #define NULL 0
00096 #endif
00097 
00098 #if !defined(DO_INLINE_P)
00099 #define DO_INLINE_P
00100 #endif
00101 
00102 #if !defined(DO_INLINE_F)
00103 #define DO_INLINE_F
00104 #endif
00105 
00106 template <class T>
00107 class vec_stdalloc {
00108  public:
00109    static T *alloc(unsigned nelems) {
00110       const size_t nbytes = nelems * sizeof(T);
00111       
00112 #ifdef _KERNEL
00113       T* result = (T*)kmem_alloc(nbytes, KM_SLEEP);
00114       // no need to assert(result) for the kernel due to KM_SLEEP flag
00115 #else
00116       T* result = (T*)malloc(nbytes);
00117       if (!result) {
00118          unsigned long lnbytes = nbytes;
00119          fprintf(stderr, "%s[%d]:  FATAL:  malloc (%lu) failed\n", __FILE__, __LINE__, lnbytes);
00120          assert(result);
00121       }
00122 #endif
00123 
00124       return result;
00125    }
00126 
00127 #ifdef _KERNEL
00128    static void free(T *vec, unsigned nelems) {
00129       kmem_free(vec, sizeof(T)*nelems);
00130    }
00131 #else   
00132    static void free(T *vec, unsigned /*nelems*/) {
00133       ::free(vec);
00134    }
00135 #endif
00136 };
00137 
00138 template<class T, class A=vec_stdalloc<T> >
00139 class pdvector {
00140  public:
00141    // A few typedefs to be compatible with stl algorithms.
00142    typedef T        value_type;
00143    typedef T*       pointer;
00144    typedef const T* const_pointer;
00145    typedef T*       iterator;
00146    typedef const T* const_iterator;
00147    typedef T&       reference;
00148    typedef const T& const_reference;
00149 
00150    pdvector() {
00151       data_ = NULL;
00152       sz_ = tsz_ = 0;
00153    }
00154    
00155 #ifndef _KERNEL
00156    explicit
00157 #endif
00158    DO_INLINE_F
00159    pdvector(unsigned sz) {
00160       // explicit: don't allow this ctor to be used as an implicit conversion from
00161       // unsigned to pdvector<T>.  So, this is disallowed:
00162       // pdvector<T> mypdvector = 3;
00163       // But this is still allowed, of course:
00164       // pdvector<T> mypdvector(3);
00165 
00166       // note: if you make use of this method, class T must have a default ctor
00167       initialize_1(sz, T());
00168    }
00169    
00170    DO_INLINE_F
00171    pdvector(unsigned sz, const T &t) {
00172       initialize_1(sz, t);
00173    }
00174 
00175    DO_INLINE_F
00176    pdvector(const pdvector<T, A> &src) {
00177       initialize_copy(src.sz_, src.begin(), src.end());
00178    }
00179 
00180    DO_INLINE_F
00181    pdvector(const pdvector<T, A> &src1, const T &src2) {
00182       // initialize as: this = src1; this += src2;
00183       sz_ = tsz_ = src1.size() + 1;
00184       data_ = A::alloc(sz_);
00185       assert(data_);
00186 
00187       // copy all of 'src1':
00188       copy_into_uninitialized_space(data_, // dest
00189                                     src1.begin(), src1.end());
00190 
00191       // copy all of 'src2':
00192       (void)new((void*)(data_ + sz_ - 1))T(src2);
00193    }
00194 
00195    DO_INLINE_F
00196    pdvector(const pdvector<T,A> &src1, const pdvector<T,A> &src2) {
00197       // initialize as: this = src1; this += src2;
00198       sz_ = tsz_ = src1.size() + src2.size();
00199       data_ = A::alloc(sz_);
00200       assert(data_);
00201       
00202       // copy all of 'src1':
00203       copy_into_uninitialized_space(data_, // dest
00204                                     src1.begin(), src1.end());
00205       
00206       // copy all of 'src2':
00207       copy_into_uninitialized_space(data_ + src1.size(), // dest
00208                                     src2.begin(), src2.end());
00209    }      
00210 
00211    DO_INLINE_F 
00212    ~pdvector() {
00213       zap();
00214    }
00215    DO_INLINE_F bool operator==(const pdvector<T, A> &) const;
00216 
00217    DO_INLINE_F pdvector<T, A>&  operator=(const pdvector<T, A> &);
00218    DO_INLINE_F pdvector<T, A>& operator+=(const pdvector<T, A> &);
00219    DO_INLINE_F pdvector<T, A>& operator+=(const T &);
00220    DO_INLINE_F 
00221    pdvector<T, A> operator+(const T &item) const {
00222       // A horribly slow routine, so use only when convenience
00223       // outshines the performance loss.
00224       pdvector<T, A> result(*this);
00225       result += item;
00226       return result;
00227    }
00228 
00229    DO_INLINE_F
00230    reference operator[] (unsigned i) {
00231       assert((i < sz_) && data_);
00232       return *(data_ + i);
00233    }
00234 
00235    DO_INLINE_F
00236    const_reference operator[] (unsigned i) const {
00237       assert((i < sz_) && data_);
00238       return *(data_ + i);
00239    }
00240 
00241    DO_INLINE_F
00242    void pop_back() { // fry the last item in the pdvector
00243       shrink(sz_ - 1);
00244    }
00245 
00246    DO_INLINE_F pdvector<T, A>& push_back(const T &);
00247 
00248    // Careful, you'll have errors if you attempt to erase an element while
00249    // iterating forward over the pdvector.  This is because the erase method
00250    // copies down later elements down to fill the hole.  Iterate from the end
00251    // back to the beginning of the pdvector if you intend to erase an element.
00252    DO_INLINE_F void erase(unsigned start, unsigned end);
00253    DO_INLINE_F void erase(iterator itr);
00254    DO_INLINE_F void sort(qsort_cmpfunc_t cmpfunc);
00255 
00256    DO_INLINE_F
00257    void swap(pdvector<T, A> &other) {
00258       T *mydata = data_;
00259       const unsigned mysz = sz_;
00260       const unsigned mytsz = tsz_;
00261       
00262       data_ = other.data_;
00263       sz_ = other.sz_;
00264       tsz_ = other.tsz_;
00265 
00266       other.data_ = mydata;
00267       other.sz_ = mysz;
00268       other.tsz_ = mytsz;
00269    }
00270 
00271    DO_INLINE_F reference       front()       { return *begin(); }
00272    DO_INLINE_F const_reference front() const { return *begin(); }
00273    DO_INLINE_F reference       back()       { return *(end()-1); }
00274    DO_INLINE_F const_reference back() const { return *(end()-1); }
00275 
00276    DO_INLINE_F unsigned size() const {return sz_;}
00277    
00278    DO_INLINE_F void resize(unsigned, bool exact=true);
00279       // note: if you use this method, class T must have a default ctor
00280       // this method simply calls shrink() or grow(), as appropriate.
00281 
00282    DO_INLINE_F void shrink(unsigned newsize);
00283       // doesn't free up any memory, so well suited if you plan to later re-add
00284       // to the pdvector.
00285 
00286    DO_INLINE_F void clear() {if (sz_ > 0) shrink(0);}
00287       // prefer clear() to resize(0) because former doesn't require a copy-ctor
00288       // Doesn't free up any memory (expects you to add to the pdvector later).
00289       // If you're pretty sure that you're done with pdvector, then prefer zap()
00290       // instead.
00291 
00292    DO_INLINE_F
00293    void zap() {
00294       // like clear() but truly frees up the pdvector's memory; 
00295       // call when you don't expect to add to the pdvector any more
00296       destroy();
00297       sz_ = tsz_ = 0;
00298    }
00299       
00300    DO_INLINE_F void grow(unsigned newsize, bool exact=false);
00301       // note: if you use this method, class T must have a default ctor
00302 
00303    DO_INLINE_F void reserve(unsigned nelems) { reserve_exact(nelems); }
00304       // for STL compatibility
00305    DO_INLINE_F void reserve_exact(unsigned nelems);
00306    DO_INLINE_F void reserve_roundup(unsigned nelems);
00307    
00308    DO_INLINE_F
00309    unsigned capacity() const {
00310       // capacity()-size() is the # of elems that can be inserted before
00311       // reallocation takes place; thus, pointers into the pdvector remain
00312       // valid until then.
00313       return tsz_;
00314    }
00315 
00316    DO_INLINE_F iterator reserve_for_inplace_construction(unsigned nelems);
00317       // allocates uninitialized memory, sets size(), returns iterator to first item.
00318       // Use placement void* operator new to initialize in place, eliminating the
00319       // need for a ctor,copy-ctor sequence.  For expert users only!
00320    
00321    DO_INLINE_F iterator append_with_inplace_construction();
00322       // Appends a single, totally uninitialized member to the pdvector.  Bumps up sz_;
00323       // reserves as needed.
00324    
00325    // iteration, stl style:
00326    DO_INLINE_F iterator       begin()       { return data_; }
00327    DO_INLINE_F const_iterator begin() const { return data_; }
00328    DO_INLINE_F iterator       end()       { return begin() + sz_; }
00329    DO_INLINE_F const_iterator end() const { return begin() + sz_; }
00330 
00331    DO_INLINE_F iterator       getIter(unsigned index)       { 
00332      assert(index < sz_);
00333      return data_ + index; 
00334    }
00335    DO_INLINE_F const_iterator getIter(unsigned index) const { 
00336      assert(index < sz_);
00337      return data_ + index;
00338    }
00339 
00340  private:
00341    DO_INLINE_P
00342    static void deconstruct_items(T *first, T *last) {
00343       for (; first != last; ++first) 
00344          first->~T();
00345    }
00346 
00347    DO_INLINE_P
00348    static void copy_into_uninitialized_space(T *dest, const T *src_first,
00349                                              const T *src_last) {
00350       // manually call copy-ctor to copy all the items from src to dest, assuming
00351       // that dest is uninitialized memory but src is properly initialized.
00352                                                 
00353       while (src_first != src_last)
00354          new((void*)dest++) T(*src_first++);
00355    }
00356 
00357    DO_INLINE_P
00358    static void copy_1item_into_uninitialized_space(T *dest, const T &src,
00359                                                    unsigned n) {
00360       while (n--)
00361          new((void*)dest++) T(src);
00362    }
00363 
00364    DO_INLINE_P void initialize_1(unsigned sz, const T &t);
00365    DO_INLINE_P void initialize_copy(unsigned sz, const T *srcfirst, const T *srcend);
00366 
00367    DO_INLINE_P void destroy();
00368 
00369    T*       data_;
00370    unsigned sz_;
00371    unsigned tsz_;
00372 };
00373 
00374 template<class T, class A>
00375 DO_INLINE_F
00376 pdvector<T, A>&
00377 pdvector<T, A>::operator=(const pdvector<T, A>& src) {
00378    if (this == &src)
00379       return *this;
00380 
00381    bool fryAndRecreate = (src.sz_ > tsz_); // or if alloc/free fns differ...
00382 
00383    if (fryAndRecreate) {
00384       // deconstruct the old pdvector and deallocate it
00385       destroy();
00386        
00387       // allocate the new pdvector and initialize it
00388       initialize_copy(src.sz_, src.begin(), src.end());
00389    }
00390    else {
00391       // deconstruct existing items
00392       deconstruct_items(begin(), end());
00393        
00394       sz_ = src.sz_; // tsz_ left unchanged
00395       copy_into_uninitialized_space(data_, // dest
00396                                     src.begin(), src.end());
00397    }
00398 
00399    return *this;
00400 }
00401 
00402 template<class T, class A>
00403 DO_INLINE_F
00404 pdvector<T, A>&
00405 pdvector<T, A>::operator+=(const pdvector<T,A>& src) {
00406    const unsigned newsize = sz_ + src.sz_;
00407    if (newsize > tsz_)
00408       reserve_roundup(newsize);
00409    
00410    copy_into_uninitialized_space(data_ + sz_, // dest
00411                                  src.begin(), src.end());
00412 
00413    sz_ += src.sz_;
00414    assert(tsz_ >= sz_); // reserve_roundup() made this so
00415 
00416    return *this;
00417 }
00418 
00419 template<class T, class A>
00420 DO_INLINE_F
00421 pdvector<T, A>&
00422 pdvector<T, A>::operator+=(const T& t) {
00423    const unsigned newsize = sz_ + 1;
00424    if (newsize > tsz_)
00425       reserve_roundup(newsize);
00426    
00427    copy_1item_into_uninitialized_space(data_ + sz_, // dest
00428                                        t, // src item
00429                                        1);
00430    sz_++;
00431    assert(tsz_ >= sz_); // reserve_roundup() made this so
00432 
00433    return *this;
00434 }
00435 
00436 template<class T, class A>
00437 DO_INLINE_F
00438 pdvector<T, A>&
00439 pdvector<T, A>::push_back(const T& t) {
00440    const unsigned newsize = sz_ + 1;
00441    if (newsize > tsz_)
00442       reserve_roundup(newsize);
00443    
00444    copy_1item_into_uninitialized_space(data_ + sz_, // dest
00445                                        t, // src item
00446                                        1);
00447    sz_++;
00448    assert(tsz_ >= sz_); // reserve_roundup() made this so
00449 
00450    return *this;
00451 }
00452 
00453 template<class T, class A>
00454 DO_INLINE_F
00455 void pdvector<T, A>::sort(qsort_cmpfunc_t cmpfunc) {
00456    if (sz_)
00457       qsort((void *) data_, sz_, sizeof(T), cmpfunc);
00458 }
00459 
00460 template<class T, class A>
00461 DO_INLINE_F
00462 void pdvector<T, A>::shrink(unsigned newsize) {
00463    if (newsize == sz_) return;
00464    if (newsize > sz_) {
00465      fprintf(stderr, "%s[%d]:  FAILING:  cannot shrink %d to %d\n", __FILE__, __LINE__, sz_, newsize);
00466    }
00467    assert(newsize < sz_);
00468    deconstruct_items(begin() + newsize, end());
00469    sz_ = newsize;
00470 }
00471 
00472 template<class T, class A>
00473 DO_INLINE_F
00474 void pdvector<T, A>::grow(unsigned newsize, bool exact) {
00475    // reallocate if tsz_ isn't big enough
00476    if (exact)
00477       reserve_exact(newsize);
00478    else
00479       reserve_roundup(newsize);
00480       
00481    copy_1item_into_uninitialized_space(data_ + sz_, // dest
00482                                        T(), // src item
00483                                        newsize - sz_);
00484    sz_ = newsize;
00485    assert(tsz_ >= sz_);
00486 }
00487 
00488 
00489 template<class T, class A>
00490 DO_INLINE_F
00491 void pdvector<T, A>::resize(unsigned newsize, bool exact) {
00492    if (newsize == sz_)
00493       ;
00494    else if (newsize < sz_)
00495       shrink(newsize);
00496    else
00497       grow(newsize, exact);
00498 }
00499 
00500 template<class T, class A>
00501 DO_INLINE_F
00502 void pdvector<T, A>::erase(unsigned start, unsigned end) {
00503     int origSz = sz_;
00504     int emptyIndex = start;
00505     int copyIndex = end + 1;
00506     while(copyIndex<origSz) {
00507         data_[emptyIndex++] = data_[copyIndex++];
00508     }
00509     /*resize(origSz - (end - start + 1)); */
00510     shrink(origSz - (end - start + 1));
00511 }
00512 
00513 template<class T, class A>
00514 DO_INLINE_F
00515 void pdvector<T, A>::erase(iterator itr) { 
00516    unsigned index = itr - data_;
00517    erase(index, index);
00518 }
00519 
00520 template<class T, class A>
00521 DO_INLINE_P
00522 void pdvector<T, A>::initialize_1(unsigned sz, const T &t) {
00523    sz_ = tsz_ = sz;
00524    if (sz_ > 0) {
00525       data_ = A::alloc(sz_);
00526       assert(data_);
00527       copy_1item_into_uninitialized_space(data_, t, sz_);
00528    }
00529    else
00530       data_ = NULL;
00531 }
00532 
00533 template<class T, class A>
00534 DO_INLINE_P
00535 void pdvector<T, A>::initialize_copy(unsigned sz, const T *srcfirst, const T *srclast) {
00536    sz_ = tsz_ = sz;
00537    if (sz_ > 0) {
00538       data_ = A::alloc(sz_);
00539       assert(data_ && srcfirst && srclast);
00540       copy_into_uninitialized_space(data_, // dest
00541                                     srcfirst, srclast);
00542    }
00543    else
00544       data_ = NULL;
00545 }
00546 
00547 template<class T, class A>
00548 DO_INLINE_P
00549 void pdvector<T, A>::destroy() {
00550    if (data_) {
00551       deconstruct_items(begin(), end());
00552       assert(tsz_ > 0);
00553       A::free(data_, tsz_); // tsz_, not sz_!
00554       data_ = NULL; // help purify find mem leaks
00555    }
00556    else {
00557       if(sz_ == 0) assert(tsz_==0);
00558    }
00559 }
00560 
00561 template<class T, class A>
00562 DO_INLINE_F
00563 void pdvector<T, A>::reserve_roundup(unsigned nelems) {
00564    // reserve *at least* nelems elements in the pdvector.
00565    assert(nelems >= sz_); // don't call us to shrink the pdvector!
00566 
00567    if (tsz_ > nelems)
00568       return; // nothing needed...(neat optimization)
00569 
00570    // round up 'nelems' to a power of two
00571    unsigned roundup_nelems = 1;
00572    while (roundup_nelems < nelems)
00573       roundup_nelems <<= 1; // multiply by 2
00574 
00575    assert(roundup_nelems >= nelems);
00576    
00577    reserve_exact(roundup_nelems);
00578 }
00579 
00580 template<class T, class A>
00581 DO_INLINE_F
00582 TYPENAME pdvector<T,A>::iterator
00583 pdvector<T, A>::append_with_inplace_construction() {
00584    reserve_roundup(sz_ + 1);
00585       // used to be reserve_exact(), but with huge performance penalty!
00586    
00587    ++sz_;
00588    
00589    return end()-1;
00590 }
00591 
00592 
00593 template<class T, class A>
00594 DO_INLINE_F
00595 TYPENAME pdvector<T, A>::iterator
00596 pdvector<T, A>::reserve_for_inplace_construction(unsigned nelems) {
00597    // NOTE: while I hunt down a certain mem leak, I'm declaring that this
00598    // routine must only be called on a default-constructor pdvector or one that
00599    // has been zap()'d (clear(0) or shrink(0) is not sufficient).
00600 
00601    assert(sz_ == 0);
00602    assert(tsz_ == 0); // too strong an assert? [see above]
00603    assert(data_ == NULL); // too strong an assert? [see above]
00604 
00605    if (nelems > 0) {
00606       //   reserve_exact(nelems);
00607 
00608       // we use the following "optimized reserve_exact()" to avoid the need for a
00609       // copy-ctor.  If we remove the above asserts then we may not have the luxury
00610       // of assuming such a trivial reserve_exact().
00611       data_ = A::alloc(nelems); // part 1 of our optimized reserve_exact()
00612       tsz_ = nelems; // part 2 of our optimized reserve_exact()
00613    }
00614    
00615    assert(sz_ == 0);
00616    assert(tsz_ >= nelems);
00617    if (nelems > 0)
00618       assert(data_ != NULL);
00619 
00620    sz_ = nelems;
00621    
00622    return begin();
00623 }
00624 
00625 template<class T, class A>
00626 DO_INLINE_F
00627 void pdvector<T, A>::reserve_exact(unsigned nelems) {
00628    // exact because we're not gonna round up nelems to a power of 2
00629    // note: sz_ doesn't change
00630 
00631    assert(nelems >= sz_); // don't use to shrink the pdvector!
00632 
00633    // Don't do a 0-size allocation, weirdness results
00634    if (nelems == 0) 
00635        return; 
00636 
00637    //if (tsz_ >= nelems)
00638    //return; // nothing needed
00639 
00640    // Alloc new pdvector
00641    T *newdata = A::alloc(nelems);
00642 
00643    // Copy items over, if any
00644    if (data_) {
00645       assert(tsz_ > 0); // it would be too strict to also assert that sz_ > 0
00646       copy_into_uninitialized_space(newdata, // dest
00647                                     begin(), end());
00648    }
00649    else
00650       assert(tsz_ == 0 && sz_ == 0);
00651 
00652    // Fry the old pdvector
00653    destroy();
00654    
00655    // Finalize
00656    data_ = newdata;
00657    tsz_ = nelems;
00658    // note: sz_ doesn't change (on purpose)
00659 }
00660 
00661 template<class T, class A>
00662 DO_INLINE_P
00663 bool
00664 find(const pdvector<T, A> &v, const T &v0, unsigned &l) {
00665     unsigned i, sz;
00666     sz = v.size();
00667     for( i = 0; i < sz; ++i ) {
00668         if( v[ i ] == v0 ) {
00669             l = i;
00670             return true;
00671         }
00672     }
00673     return false;
00674 }
00675 
00676 template<class T, class A>
00677 DO_INLINE_P
00678 bool pdvector<T, A>::operator== (const pdvector<T,A> &) const
00679 {
00680   return false;
00681 }
00682 #endif /* cap_use_pdvector */
00683 #endif /* !defined(_Pdvector_h_) */
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1