fails to link with GCC on mac .. works with VC on Win. What's wrong and how to fix?

I

Inertial

I have the following source (cut down from a larger real source code).

It compiles and links and runs ok in MS VC2008 with extensions turned off
.... under GCC on a mac, it compiles, but linker complains

===
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

template<> Test<int> :: SubClass Test<int> :: statics;

int _tmain(int argc, _TCHAR* argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
===

Any ideas as to why this won't link and how to make this work???
 
I

Ian Collins

I have the following source (cut down from a larger real source code).

It compiles and links and runs ok in MS VC2008 with extensions turned
off .... under GCC on a mac, it compiles, but linker complains
how?

===
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

template<> Test<int> :: SubClass Test<int> :: statics;

int _tmain(int argc, _TCHAR* argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
===

Any ideas as to why this won't link and how to make this work???

Use the correct form of main.
 
I

Inertial

"Ian Collins" wrote in message news:[email protected]...

How what?
===
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

template<> Test<int> :: SubClass Test<int> :: statics;

int _tmain(int argc, _TCHAR* argv[])

sorry .. should be 'main' and 'char' ... not '_tmain' and '_TCHAR' (which
was from my VC version .. copied wrong one)
Use the correct form of main.

Not at all helpful.

I've got a gcc onto my windows PC so can confirm

Here is correct source...

==
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

template<> Test<int> :: SubClass Test<int> :: statics;

int main(int argc, char* argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
==

Here is error message

C:\Users\Roger\AppData\Local\Temp/ccusaaaa.o:bug.cpp:(.text+0x17): undefined
reference to `Test<int>::statics'

So .. any help please on this?
 
I

Inertial

"Inertial" wrote in message

Further .. note that if I do NOT use a class within the class .. it works
i.e. this works

==
template <class T> class Test {
public:
static int i;
};

template<> int Test<int>::i = 1;

int main (int argc, char * const argv[])
{
int j = Test<int> :: i;
return 0;
}
==

this fails

==
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

template<> Test<int> :: SubClass Test<int> :: statics;

int main(int argc, char* const argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
==
 
Ö

Öö Tiib

"Ian Collins"  wrote in message

How what?
===
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};
template<> Test<int> :: SubClass Test<int> :: statics;
int _tmain(int argc, _TCHAR* argv[])

sorry .. should be 'main' and 'char' ... not '_tmain' and '_TCHAR' (which
was from my VC version .. copied wrong one)
Use the correct form of main.

Not at all helpful.

I've got a gcc onto my windows PC so can confirm

Here is correct source...

==
template <class T> class Test {
public:
    class SubClass {
    public:
        SubClass() : i(1) {}
        int i;
    };
    static SubClass statics;

};

template<> Test<int> :: SubClass Test<int> :: statics;

int main(int argc, char* argv[])
{
    int j = Test<int> :: statics.i;
    return 0;}

==

Here is error message

C:\Users\Roger\AppData\Local\Temp/ccusaaaa.o:bug.cpp:(.text+0x17): undefined
reference to `Test<int>::statics'

So .. any help please on this?

Add such line after first "==" of yours and try again:

struct SubClass { int i; };
 
I

Inertial

"Öö Tiib" wrote in message
Add such line after first "==" of yours and try again:

struct SubClass { int i; };

That will then have TWO SubClass classes defined .. one global and one
within the Test<T> template class. So not really an answer and doesn't help
 
Ö

Öö Tiib

"Öö Tiib"  wrote in message




That will then have TWO SubClass classes defined .. one global and one
within the Test<T> template class.  So not really an answer and doesn't help

OK ... then remove template<> before:

Test<int> :: SubClass Test<int> :: statics;
 
I

Inertial

"Öö Tiib" wrote in message
OK ... then remove template<> before:

Test<int> :: SubClass Test<int> :: statics;

No .. that is required (tho older compilers compile without it).

Gcc will give a compiler error if it is missing

error: too few template-parameter-lists

So again, does not help
 
I

Inertial

"Inertial" wrote in message

also note that moving the 'Subclass' out of the template class Test does not
help.

So this also fails to link with the same message

==
template <class T> class SubClass {
public:
SubClass() : i(1) {}
int i;
};

template <class T> class Test {
public:
static SubClass<T> statics;
};

template<> SubClass<int> Test<int> :: statics;

int main(int argc, char* const argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
==

C:\Users\Roger\AppData\Local\Temp/cc0oeaaa.o:bug3.cpp:(.text+0x17):
undefined reference to `Test<int>::statics'
 
I

Inertial

However, moving the 'Subclass' and the static out DOES work ..

==
template <class T> class SubClass {
public:
SubClass() : i(1) {}
int i;
};

SubClass<int> statics;

template <class T> class Test {
public:
};

int main(int argc, char* const argv[])
{
int j = statics.i;
return 0;
}
==

but it still doesn't answer the question as to why the following code fails

==
template <class T> class SubClass {
public:
SubClass() : i(1) {}
int i;
};

template <class T> class Test {
public:
static SubClass<T> statics;
};

template<> SubClass<int> Test<int> :: statics;

int main(int argc, char* const argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
==

C:\Users\Roger\AppData\Local\Temp/cc0oeaaa.o:bug3.cpp:(.text+0x17):
undefined reference to `Test<int>::statics'

So I'd still like some answer on why the above code gets that error ! :)
 
Ö

Öö Tiib

"Öö Tiib"  wrote in message




No .. that is required (tho older compilers compile without it).

Gcc will give a compiler error if it is missing

error: too few template-parameter-lists

So again, does not help

Hmm. I do not really know what is wrong with your strange compiler
there. The example you posted should compile and link like it was.
 
I

Inertial

"Inertial" wrote in message

Note that the code above that does 'work' has the problem that if I want
specialisation other than just Test<int> that I can't (back in my original
larger project) .. as I would need a different global var for each
SubClass<T> type.

So would still like to know if there is some syntax change that can make
original code compile... ie

==
template <class T> class Test {
public:
class SubClass {
public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

template<> Test<int> :: SubClass Test<int> :: statics;

int main(int argc, char* const argv[])
{
int j = Test<int> :: statics.i;
return 0;
}
==

any ideas?
 
I

Inertial

"Öö Tiib" wrote in message
Hmm. I do not really know what is wrong with your strange compiler
there. The example you posted should compile and link like it was.

GCC on mac fails .. GCC on windows fails. Looks like its how GCC behaves ..
I don't know why GCC should be 'strange'. Its usually pretty good with
getting things right.
 
Ö

Öö Tiib

However, moving the 'Subclass' and the static out DOES work ..

==
template <class T> class SubClass {
public:
    SubClass() : i(1) {}
    int i;

};

SubClass<int> statics;

template <class T> class Test {
public:

};

int main(int argc, char* const argv[])
{
    int j = statics.i;
    return 0;}

==

but it still doesn't answer the question as to why the following code fails

==
template <class T> class SubClass {
public:
    SubClass() : i(1) {}
    int i;

};

template <class T> class Test {
public:
    static SubClass<T> statics;

};

template<> SubClass<int> Test<int> :: statics;

int main(int argc, char* const argv[])
{
    int j = Test<int> :: statics.i;
    return 0;}

==

C:\Users\Roger\AppData\Local\Temp/cc0oeaaa.o:bug3.cpp:(.text+0x17):
undefined reference to `Test<int>::statics'

So I'd still like some answer on why the above code gets that error ! :)

Maybe it is some strange thing about name mangling? Did you try with g+
+?
 
Ö

Öö Tiib

"Öö Tiib"  wrote in message



GCC on mac fails .. GCC on windows fails.  Looks like its how GCC behaves ..
I don't know why GCC should be 'strange'.  Its usually pretty good with
getting things right.

There must be something utterly wrong. Some sort of bad DEVC++ project
file, wrongly installed GCC ... really strange.
 
I

Inertial

"Öö Tiib" wrote in message
Maybe it is some strange thing about name mangling? Did you try with g++?

You mean the g++ that is part of gcc .. yeup.

Have YOU tried the code? If so, did it work? And if so using what compiler
and version
 
I

Inertial

"Öö Tiib" wrote in message
There must be something utterly wrong. Some sort of bad DEVC++ project
file, wrongly installed GCC ... really strange.

What DEVC++ project file? Just freshly installed a GCC environment .. used
"c++ bug.cpp" where bug.cpp is the 'bad' code, and get the error. Also used
the gcc compiler for XCode on a Mac .. same thing. VS2008 C++ compiler
doesn't complain, however, but its not as standard conforming.

Have YOU tried to compile the examples that failed (and worked) that I
posted .. and if so, using which compiler and version?
 
J

Jonathan Lee

Here is correct source...

==
template <class T> class Test {
public:
    class SubClass {
    public:
        SubClass() : i(1) {}
        int i;
    };
    static SubClass statics;

};

template<> Test<int> :: SubClass Test<int> :: statics;

I haven't checked the spec, but this appears to be working as
a declaration instead of definition. I did the following and it
worked fine...

template<>
class Test<int> {
public:
class SubClass {

public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

Test<int>::SubClass Test<int>::statics;

Also, this worked, but implies a copy constructor

template<> Test<int>::SubClass Test<int>::statics = SubClass();

I haven't checked, but I assume the way you wrote it is
being treated as specialization only, and not definition.

--Jonathan
 
G

Geoff

"Öö Tiib" wrote in message


You mean the g++ that is part of gcc .. yeup.

Have YOU tried the code? If so, did it work? And if so using what compiler
and version

g++ and gcc are the same under Xcode. I get the same error on OS/X
10.4 and gcc 4.0.1 under Xcode 2.5.
 
I

Ian Collins

I haven't checked the spec, but this appears to be working as
a declaration instead of definition. I did the following and it
worked fine...

Yes, it looks like the declaration of a specialisation.
template<>
class Test<int> {
public:
class SubClass {

public:
SubClass() : i(1) {}
int i;
};
static SubClass statics;
};

Test<int>::SubClass Test<int>::statics;

That is how it should be.
 

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,012
Latest member
RoxanneDzm

Latest Threads

Top