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

I

Inertial

"Jonathan Lee" wrote in message
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;

That gets an error in more recent standard conforming gcc complers .. you
get

error: too few template-parameter-lists
Also, this worked, but implies a copy constructor

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

That *may* help me though .. but still would be nice to avoid that
I haven't checked, but I assume the way you wrote it is
being treated as specialization only, and not definition.

That is what I am thinking . .but don't see yet why that is or how to force
it to be a definition.
 
Ö

Öö Tiib

"Öö Tiib"  wrote in message








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?

I tried with icc 10 and VS 2005. Comeau online does not link and no
gcc on this PC. Did you actually try to remove that template<> there?
It is strange that your compiler requires it.
 
J

Jonathan Lee

"Jonathan Lee"  wrote in message



That gets an error in more recent standard conforming gcc complers .. you
get

error: too few template-parameter-lists

Really? Doesn't do it for me on g++ 4.4.4 and that's pretty new...

--Jonathan
 
I

Inertial

"Ian Collins" wrote in message news:[email protected]...
That is how it should be.

No .. it shouldn't .. that gives error ...

error: too few template-parameter-lists

see http://c2.com/cgi/wiki?TooFewTemplateParameterLists

"Too Few Template-Parameter-Lists is an error message produced by newer
versions of the GnuCpp compiler for code which previously compiled. The
problem concerns the initialization of static members of a templated class.
Previously it was sufficient to declare the member, but this now has to be
preceded by template <>."
 
I

Inertial

"Jonathan Lee" wrote in message
Really? Doesn't do it for me on g++ 4.4.4 and that's pretty new...

I've got 4.3 here on windows .. where do I get a build 4.4.4 for Windows?
Also using it on XCode on Mac which is 4.2

Also refer to

http://c2.com/cgi/wiki?TooFewTemplateParameterLists

"TooFewTemplateParameterLists is an error message produced by newer versions
of the GnuCpp compiler for code which previously compiled. The problem
concerns the initialization of static members of a templated class.
Previously it was sufficient to declare the member, but this now has to be
preceded by template <>."

Has this changed since 4.3 ??
 
J

Jonathan Lee

"Ian Collins"  wrote in message


No .. it shouldn't .. that gives error ...

error: too few template-parameter-lists

seehttp://c2.com/cgi/wiki?TooFewTemplateParameterLists

"Too Few Template-Parameter-Lists is an error message produced by newer
versions of the GnuCpp compiler for code which previously compiled. The
problem concerns the initialization of static members of a templated class.
Previously it was sufficient to declare the member, but this now has to be
preceded by template <>."

I think you're missing the specialization of Test that I added.

--Jonathan
 
I

Inertial

"Jonathan Lee" wrote in message
I think you're missing the specialization of Test that I added.

I tried your code

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

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

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

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

and get

bug5.cpp:2: error: 'Test' is not a template
bug5.cpp:2: error: explicit specialization of non-template 'Test'
bug5.cpp:13: error: 'Test' is not a template
bug5.cpp:13: error: expected initializer before 'Test'
bug5.cpp: In function 'int main(int, char* const*)':
bug5.cpp:17: error: 'statics' was not declared in this scope
--Jonathan
 
J

Jonathan Lee

"Jonathan Lee"  wrote in message

I think you're missing the specialization of Test that I added.

I tried your code
[snip]

and get

bug5.cpp:2: error: 'Test' is not a template
bug5.cpp:2: error: explicit specialization of non-template 'Test'
bug5.cpp:13: error: 'Test' is not a template
bug5.cpp:13: error: expected initializer before 'Test'
bug5.cpp: In function 'int main(int, char* const*)':
bug5.cpp:17: error: 'statics' was not declared in this scope
--Jonathan

Sorry, I assumed you would keep the original class template.
For the sake of completeness:

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

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

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

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

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

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

--Jonathan
 
Ö

Öö Tiib

"Jonathan Lee"  wrote in message



I've got 4.3 here on windows .. where do I get a build 4.4.4 for Windows?
Also using it on XCode on Mac which is 4.2

Also refer to

http://c2.com/cgi/wiki?TooFewTemplateParameterLists

"TooFewTemplateParameterLists is an error message produced by newer versions
of the GnuCpp compiler for code which previously compiled. The problem
concerns the initialization of static members of a templated class.
Previously it was sufficient to declare the member, but this now has to be
preceded by template <>."

Has this changed since 4.3 ??

What happens if you do not specialize that Test<int>::statics? I mean
write something like:

template<class T> typename Test<T> :: SubClass Test<T> :: statics;
 
I

Inertial

"Jonathan Lee" wrote in message
Sorry, I assumed you would keep the original class template.
For the sake of completeness:
]snip]

EWW .. having to specify the whole class twice seems a bit on the awful side

This works just fine, however

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

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

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

No copy constructor or operator = required .. so hoping it also doesn't
double construct.
 
J

Jonathan Lee

Yes, it looks like the declaration of a specialisation.

Just for anyone who is wondering, I dug up the relevant part of
the spec (emphasis mine):

[temp.expl.spec]

14. An explicit specialization of a static data
member of a template is a definition if the declaration includes
an initializer; otherwise, it is a *declaration*. [Note: there is
*no* syntax for the definition of a static data member of a
template that requires default initialization.

template<> X Q<int>::x;

15. This is a *declaration* regardless of whether X can be
default initialized. -- end note]

--Jonathan
 
I

Inertial

"Jonathan Lee" wrote in message

Yes, it looks like the declaration of a specialisation.
Just for anyone who is wondering, I dug up the relevant part of
the spec (emphasis mine):

[temp.expl.spec]

14. An explicit specialization of a static data
member of a template is a definition if the declaration includes
an initializer; otherwise, it is a *declaration*. [Note: there is
*no* syntax for the definition of a static data member of a
template that requires default initialization.
Nasty

template<> X Q<int>::x;

But this form will work (in my case at least) ...

template said:
15. This is a *declaration* regardless of whether X can be
default initialized. -- end note]
 
I

Inertial

"Inertial" wrote in message

DAMNIT !!!

All is fine .. except in my REAL example, one of my members explicitly has a
private copy constructor .. so it is the equivalent of this ...

==
class NoCopyConstructor {
public:
NoCopyConstructor() {}
private:
NoCopyConstructor(const NoCopyConstructor& x); // no copy constructor
};

template <class T> class Test {
public:
class InnerClass {
public:
InnerClass() : i(1) {}
int i;
NoCopyConstructor x;
};
static InnerClass statics;
};

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

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

And THAT fails to compile. So think I might put in a dummy arg to the
constructor for the InnerClass and see if that works .. let you know ::)
 
I

Inertial

"Inertial" wrote in message

ok .. now THIS works ok

==
class NoCopyConstructor {
public:
NoCopyConstructor() {}
private:
NoCopyConstructor(const NoCopyConstructor& x); // no copy constructor
};

template <class T> class Test {
public:
class InnerClass {
public:
InnerClass(bool) : i(1) {}
T i;
NoCopyConstructor x;
};
static InnerClass statics;
};

template<> Test<int> :: InnerClass Test<int> :: statics(true);

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

Öö Tiib

"Inertial"  wrote in message




DAMNIT !!!

All is fine .. except in my REAL example, one of my members explicitly has a
private copy constructor .. so it is the equivalent of this ...

==
class NoCopyConstructor {
public:
    NoCopyConstructor() {}
private:
    NoCopyConstructor(const NoCopyConstructor& x);    // no copy constructor

};

template <class T> class Test {
public:
    class InnerClass {
    public:
        InnerClass() : i(1) {}
        int i;
        NoCopyConstructor x;
    };
    static InnerClass statics;

};

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

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

==

And THAT fails to compile.  So think I might put in a dummy arg to the
constructor for the InnerClass and see if that works .. let you know ::)

Still why you do not try it without that specialization?

template<class T> typename Test<T> :: InnerClass Test<T> :: statics;
 
I

Inertial

"Öö Tiib" wrote in message
Still why you do not try it without that specialization?

template<class T> typename Test<T> :: InnerClass Test<T> :: statics;

That seems to work too :)

But in my real project ding it that way won't help, as that doesn't actually
force the definition of statics at a particular point in code .. and for
order of construction/destruction I have to make it define given instances
of the class at a particular point in a particular file.

Thanks tho
 
I

Ian Collins

"Öö Tiib" wrote in message


That seems to work too :)

But in my real project ding it that way won't help, as that doesn't
actually force the definition of statics at a particular point in code
.. and for order of construction/destruction I have to make it define
given instances of the class at a particular point in a particular file.

That is never a good idea! It'll work fine until something gets added,
or something gets moved to another file.
 
V

Vladimir Jovic

Öö Tiib said:
What happens if you do not specialize that Test<int>::statics? I mean
write something like:

template<class T> typename Test<T> :: SubClass Test<T> :: statics;

I tried that on g++ 4.3, and it compiled fine.



If it helps, next code also compiles fine :

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


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

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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top