Topic: template bug or syntax error?


Author: Terence Kelling <kelling@arlut.utexas.edu>
Date: 1998/05/20
Raw View
I am having the worst time trying to compile a template class in MS
Visual C++ ver 5.0 service pack 3 that defines member functions outside
of the class definition body.  The following works fine if I define the
functions inside of the class, but when I define them outside, I get the
following error.  To make matters more complicated, this will work fine
if I only declare either the non-const or const version and define it
outside of the class body.

Is this a bug or am I doing something wrong?

Thanks,
Terence

main.obj : error LNK2001: unresolved external symbol
"public: int * __thiscall container<int,class
std::allocator<int>>::begin(void)"
   (?begin@?$container@HV?$allocator@H@std@@@@QAEPAHXZ)


#include <climits>
#include <memory>
#include <stdexcept>
#include <xutility>

using namespace std;

template<class T, class A = allocator<T> >
class container {

   public:
      // typedefs
    typedef container<T, A> _Myt;
    typedef A::pointer _Tptr;
    typedef A::const_pointer _Ctptr;
    typedef _Tptr iterator;
    typedef _Ctptr const_iterator;

      // constructors
      explicit container(const A& Al = A()) : allocator_m(Al), base_m(0)
{

         base_m = allocator_m.allocate(10, (void *)0);
      }


      // destructor
      ~container() {
     allocator_m.deallocate(base_m, 10);
      }


      // get/set methods
      iterator begin(void);// { return base_m; }
      const_iterator begin(void) const;// { return ((const_iterator)
base_m); }


   private:
      A allocator_m;
    iterator base_m;
};


template<class T, class A> inline
container<T, A>::iterator container<T, A>::begin(void) {

   return base_m;
}

template<class T, class A> inline
container<T, A>::const_iterator container<T, A>::begin(void) const {

   return ((const_iterator) base_m);
}


int main(void) {

   container<int> c;

   container<int>::iterator begin = c.begin();

   return 0;
};



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Terence Kelling <kelling@arlut.utexas.edu>
Date: 1998/05/20
Raw View
I have narrowed the problem down to a problem with typedefs. MSVC seems
to have a problem with multiple typedefs.  If I compile the code with
the typedefs given as comments, everything works fine, but if I compile
it as below, I get the linker error.  Furthermore, if I put class foo
in a header file of it's own and include that file from main, I get
fatal error C1001:  INTERNAL COMPILER ERROR.

Just to verify, am I missing a subtlety of C++ or is this a compiler bug?

Thanks,
Terence Kelling

#include <memory>
using namespace std;

template <class T, class A = allocator<T> >
class foo {

   public:
      typedef A::pointer iterator;              // typedef T* iterator;
      typedef A::const_pointer const_iterator;  // typedef const T*
      // const_iterator;

      iterator begin(void);
      const_iterator begin(void) const;

   private:
      A allocator_m;
      iterator base_m;
};


template <class T, class A> inline
foo<T, A>::iterator foo<T, A>::begin(void) {

   return base_m;
}

template <class T, class A> inline
foo<T, A>::const_iterator foo<T, A>::begin(void) const {

   return base_m;
}

// #include "foo.h"  // fatal error if you put the above in a header
                     // file and try to include it

int main(void) {

   foo<int> f;

   int* ptr = f.begin();

   return 0;
};
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1998/05/21
Raw View
Terence Kelling <kelling@arlut.utexas.edu> writes:

> Just to verify, am I missing a subtlety of C++ or is this a compiler bug?

It may be a completely unrelated problem, but you're definitely
missing the `typename' keyword, that is mandatory before
template-argument dependent type names.

>       typedef A::pointer iterator;              // typedef T* iterator;
>       typedef A::const_pointer const_iterator;  // typedef const T*
>       // const_iterator;

Make this:
 typedef typename A::pointer iterator;
 typedef typename A::const_pointer const_iterator;

And it may work.

--
Alexandre Oliva
mailto:oliva@dcc.unicamp.br mailto:aoliva@acm.org
http://www.dcc.unicamp.br/~oliva
Universidade Estadual de Campinas, SP, Brasil


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]