compiler specific: gcc and templates

C

Chameleon

This code below compiles fine with VS.2005 but with gcc 3.4.2 not.
------------------
template<class T>
static void Wastage1D::clever_erase(vector<T> &v, vector<typename
vector<T>::iterator> &its, vector<T> &vo)
{ ........ }
------------------

I run gcc like this:
gcc -c wastage1d.cpp

The error message of gcc:
------------------
wastage1d.cpp:140: error: cannot declare member function `static void
wastage::Wastage1D::clever_erase(std::vector said:
>&, std::vector<typename std::vector<T, std::allocator<_CharT>
>::iterator, std::allocator<typename std::vector<T,
std::allocator<_CharT> >::iterator> >&, std::vector<T,
std::allocator<_CharT> >&)' to have static linkage
wastage1d.cpp: In static member function `static void
wastage::Wastage1D::clever_erase(std::vector said:
>&, std::vector<typename std::vector<T, std::allocator<_CharT>
>::iterator, std::allocator<typename std::vector<T,
std::allocator<_CharT> >::iterator> >&, std::vector<T,
std::allocator<_CharT> >&)':
 
J

Jonathan Mcdougall

Chameleon said:
This code below compiles fine with VS.2005 but with gcc 3.4.2 not.
------------------
template<class T>
static void Wastage1D::clever_erase(vector<T> &v, vector<typename
vector<T>::iterator> &its, vector<T> &vo)
{ ........ }
------------------

I run gcc like this:
gcc -c wastage1d.cpp

The error message of gcc:
------------------
wastage1d.cpp:140: error: cannot declare member function `static void

std::allocator<_CharT> >::iterator> >&, std::vector<T,
std::allocator<_CharT> >&)' to have static linkage
wastage1d.cpp: In static member function `static void

std::allocator<_CharT> >::iterator> >&, std::vector<T,
std::allocator<_CharT> >&)':

It seems like you put 'static' not only on the member function
declaration, but on the definition too. Drop the one on the definition.

class C
{
static void f();
};

void C::f() // <-- no static here
{
}


Jonathan
 
C

Chameleon

Jonathan said:
It seems like you put 'static' not only on the member function
declaration, but on the definition too. Drop the one on the definition.

class C
{
static void f();
};

void C::f() // <-- no static here
{
}

ok and thanks!
but I have one last problem (the same: VS.2005 does, gcc doesn't)
-------------------
template<class T>
void Wastage1D::clever_erase(vector<T> &v, vector<typename
vector<T>::iterator> &its, vector<T> &vo)
{
// ....... code .......
vector<T>::iterator cur = its.front(), curo = its.front();
vector<typename vector<T>::iterator>::iterator itscur = its.begin();
// ....... code .......
}
-------------------

gcc fails to compile with this message:
-------------------
wastage1d.cpp:148: error: expected `;' before "cur"
wastage1d.cpp:149: error: expected `;' before "itscur"
-------------------

how can I put ";" before "cur" or "itscur"?

after all these, I believe, for cross-platform code, its better to use
first gcc (until the completion of the program) and after VS.

thank you
 
J

Jonathan Mcdougall

Chameleon said:
template<class T>
void Wastage1D::clever_erase(vector<T> &v, vector<typename
vector<T>::iterator> &its, vector<T> &vo)
{
// ....... code .......
vector<T>::iterator cur = its.front(), curo = its.front();
vector<typename vector<T>::iterator>::iterator itscur = its.begin();
// ....... code .......
}

:)

Either you are inattentive or you didn't write part of the code because
the answer is right there :

vector<typename vector<T>::iterator>::iterator itscur
^^^^^^^^^^^

When a name depends on a template parameter, you must use typename to
indicate to the compiler that what follows is a type name and nothing
else. So your code becomes:

typename vector<T>::iterator cur = its.front(), curo = its.front();
after all these, I believe, for cross-platform code, its better to use
first gcc (until the completion of the program) and after VS.

The more conforming the compiler is, the better, yes.


Jonathan
 
C

Chameleon

simpler sample:

---------------
#include <vector>
using namespace std;

template <class T> class c1 {
public:
static void c() {
vector<T>::iterator f;
}
};

int main() { c1<int> c; }
---------------

if I change for instance the line
vector<T>::iterator f;
with
vector<T> f;
works.

the error message:
 
C

Chameleon

Jonathan said:
:)

Either you are inattentive or you didn't write part of the code because
the answer is right there :

vector<typename vector<T>::iterator>::iterator itscur
^^^^^^^^^^^

When a name depends on a template parameter, you must use typename to
indicate to the compiler that what follows is a type name and nothing
else. So your code becomes:

typename vector<T>::iterator cur = its.front(), curo = its.front();


The more conforming the compiler is, the better, yes.

it works! it works!
thanks a lot

Finally, the problem is that, I know only the basics about templates in
C++. The problem in above code, was only a symptom...

I must read.
 
J

Jonathan Mcdougall

Chameleon said:
simpler sample:

---------------
#include <vector>
using namespace std;

template <class T> class c1 {
public:
static void c() {
vector<T>::iterator f;
}
};

int main() { c1<int> c; }
---------------

if I change for instance the line
vector<T>::iterator f;
with
vector<T> f;
works.

the error message:

Is that a question? If so, ask it plainly and remember to quote the
message are answering to.

The problem with the line

vector<T>::iterator f;

is that the compiler, at the time it sees this line, may be unable to
know what the definition of vector<> is for that specific T. Since
templates may be specialized, vector<A>::iterator could be a type and
vector<B>::iterator could be an object:

class A {};
class B {};

template <class T>
class vector;

template<>
class vector<A>
{
public:
typedef int iterator; // just an example
};

template<>
class vector<B>
{
public:
int iterator;
};

template <class T>
void f()
{
vector<T>::iterator itor; // what is 'iterator' here?
}

The language says that in this case, vector<T>::iterator sould be
considered as an object, not a type (it may be either one here,
depending on whether T is A or B). Adding 'typename' in front indicates
that 'iterator' is a type, not an object.

template <class T>
void f()
{
typename vector<T>::iterator itor; // 'iterator' is a type
}

As for using vector<T> directly, it poses no problem to the compiler
since that name must be declared before it is used. It is easy for the
compiler to decide whether it is a type or not.


Jonathan
 
L

Larry I Smith

Chameleon said:
This code below compiles fine with VS.2005 but with gcc 3.4.2 not.
------------------
template<class T>
static void Wastage1D::clever_erase(vector<T> &v, vector<typename
vector<T>::iterator> &its, vector<T> &vo)
{ ........ }
<snip>

Use 'gcc' to compile & link C code, and 'g++' to
compile & link C++ code. So...

g++ -c wastage1d.cpp

produces 'wastage1d.o' (or 'wastage1d.obj' on Windows?).


Than later, to link the executable 'wastage' (all on
one line - linux/unix example)...

g++ wastage1d.o other.o another.o -lsomelib -lanotherlib
-owastage

'g++' invokes the linker, passing it the correct options
and default libs. The syntax may differ slightly on Windows,
read the gcc/g++ docs.

Larry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top