468,791 Members | 1,823 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,791 developers. It's quick & easy.

Defining static members in explicit specializations

I'm writing a class similar to this:

#include <iostream>
using namespace std;

template<class t> class Foo
{
private:
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}
};
static Bar x;
t y;
};

template<> Foo<int>::Bar Foo<int>::x;

int main()
{
return 0;
}

When executed, it should print "hello, world" to the console, which it
does when compiled with Sun's CC compiler. However, it does nothing
when compiled with GCC (versions 4.0.2 and older). GCC-compiled
versions produce the expected output when Foo is made into a normal,
rather than template, class, or when Foo::x is made into a pointer and
initialized with a dynamically-allocated object. Is this a bug in GCC,
or one of those poorly-specified edge cases in C++?

Rennie
Dec 30 '05 #1
9 1363
If you change the line:

template<> Foo<int>::Bar Foo<int>::x:

to

Foo<int>::Bar Foo<int>::x;

it works fine. The syntax you used is for partial template
specialization, which is not what you want here. All you want is to
refer to (and initialize) the (static) member named "x", of type
Foo<int>::Bar, of class Foo<int>.

Luke

Dec 30 '05 #2
AD
I made slight modifications to your program and it worked.
a) I changed the initialisation of static member of template class Foo
as following:
"template<class t> Foo<t>::Bar Foo<t>::x;"
This initializes x for all typenames and not only int.
b) I added a function to class Bar and then used x in Foo to call this
function.
This caused x to be instantiated and Bar constructor was called. This
is explained by concept that template members are initialised at the
first point of use in program and not necessarily at the
definition/declaration. So mere declaration/definition of static member
of template class wont instantiate it.

Following is the changed program and it worked with g++ compiler.

#include <iostream>
using namespace std;

template<class t> class Foo
{
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}

void Call()
{
cout<<"Bar::Call"<<endl;
}
};
public:
static Bar x;
t y;

};

template<class t> Foo<t>::Bar Foo<t>::x;

int main()
{
Foo<int> f;
Foo<int>::x.Call();

return 0;
}
/**************************/

Dec 30 '05 #3
Luke Meyers wrote:
If you change the line:

template<> Foo<int>::Bar Foo<int>::x:

to

Foo<int>::Bar Foo<int>::x;

it works fine. The syntax you used is for partial template
specialization, which is not what you want here. All you want is to
refer to (and initialize) the (static) member named "x", of type
Foo<int>::Bar, of class Foo<int>.

Luke


If I do that, gcc barfs with this message:

test.cpp:19: error: too few template-parameter-lists

Rennie
Dec 30 '05 #4
AD wrote:
I made slight modifications to your program and it worked.
a) I changed the initialisation of static member of template class Foo
as following:
"template<class t> Foo<t>::Bar Foo<t>::x;"
This initializes x for all typenames and not only int.
b) I added a function to class Bar and then used x in Foo to call this
function.
This caused x to be instantiated and Bar constructor was called. This
is explained by concept that template members are initialised at the
first point of use in program and not necessarily at the
definition/declaration. So mere declaration/definition of static member
of template class wont instantiate it.

Following is the changed program and it worked with g++ compiler.

#include <iostream>
using namespace std;

template<class t> class Foo
{
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}

void Call()
{
cout<<"Bar::Call"<<endl;
}
};
public:
static Bar x;
t y;

};

template<class t> Foo<t>::Bar Foo<t>::x;

int main()
{
Foo<int> f;
Foo<int>::x.Call();

return 0;
}
/**************************/


g++ 4.0.2 throws the following error on that code (although g++ 2.95.3
accepts it):

test.cpp:25: error: expected constructor, destructor, or type conversion
before ‘Foo’

Rennie
Dec 30 '05 #5

Rennie deGraaf wrote:
AD wrote:
I made slight modifications to your program and it worked.
a) I changed the initialisation of static member of template class Foo
as following:
"template<class t> Foo<t>::Bar Foo<t>::x;"
This initializes x for all typenames and not only int.
b) I added a function to class Bar and then used x in Foo to call this
function.
This caused x to be instantiated and Bar constructor was called. This
is explained by concept that template members are initialised at the
first point of use in program and not necessarily at the
definition/declaration. So mere declaration/definition of static member
of template class wont instantiate it.

Following is the changed program and it worked with g++ compiler.

#include <iostream>
using namespace std;

template<class t> class Foo
{
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}

void Call()
{
cout<<"Bar::Call"<<endl;
}
};
public:
static Bar x;
t y;

};

template<class t> Foo<t>::Bar Foo<t>::x;

int main()
{
Foo<int> f;
Foo<int>::x.Call();

return 0;
}
/**************************/


g++ 4.0.2 throws the following error on that code (although g++ 2.95.3
accepts it):

test.cpp:25: error: expected constructor, destructor, or type conversion
before 'Foo'

Rennie


I believe you need to declare Foo<t>::Bar as a typename, like so:
template<class t> typename Foo<t>::Bar Foo<t>::x;

g++4.0.0 then accepts it.

-matt

Dec 30 '05 #6
Rennie deGraaf wrote:
I'm writing a class similar to this:

#include <iostream>
using namespace std;

template<class t> class Foo
{
private:
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}
};
static Bar x;
t y;
};

template<> Foo<int>::Bar Foo<int>::x;

int main()
{
return 0;
}

When executed, it should print "hello, world" to the console, which it
does when compiled with Sun's CC compiler. However, it does nothing
when compiled with GCC (versions 4.0.2 and older). GCC-compiled
versions produce the expected output when Foo is made into a normal,
rather than template, class, or when Foo::x is made into a pointer and
initialized with a dynamically-allocated object. Is this a bug in GCC,
or one of those poorly-specified edge cases in C++?

Rennie


We discussed a similar problem in this thread (see especially the posts
by James Kanze):

http://groups.google.com/group/comp....48a992ba350f2f

In essence, though GCC's is not the behavior you want, it is the more
standard-conformant compiler on this point, and Sun is incorrect. The
static member x should not be instantiated unless it is actually
referenced, which it is not in your sample program. You can force
instantiation on a conforming compiler by adding a trivial reference to
x somewhere, e.g. in the destructor for Foo<> with something like this:

~Foo() { (void)&x; }

Cheers! --M

Dec 30 '05 #7
Matteo wrote:
Rennie deGraaf wrote:
AD wrote:
I made slight modifications to your program and it worked.
a) I changed the initialisation of static member of template class Foo
as following:
"template<class t> Foo<t>::Bar Foo<t>::x;"
This initializes x for all typenames and not only int.
b) I added a function to class Bar and then used x in Foo to call this
function.
This caused x to be instantiated and Bar constructor was called. This
is explained by concept that template members are initialised at the
first point of use in program and not necessarily at the
definition/declaration. So mere declaration/definition of static member
of template class wont instantiate it.

Following is the changed program and it worked with g++ compiler.

#include <iostream>
using namespace std;

template<class t> class Foo
{
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}

void Call()
{
cout<<"Bar::Call"<<endl;
}
};
public:
static Bar x;
t y;

};

template<class t> Foo<t>::Bar Foo<t>::x;

int main()
{
Foo<int> f;
Foo<int>::x.Call();

return 0;
}
/**************************/


g++ 4.0.2 throws the following error on that code (although g++ 2.95.3
accepts it):

test.cpp:25: error: expected constructor, destructor, or type conversion
before 'Foo'

Rennie

I believe you need to declare Foo<t>::Bar as a typename, like so:
template<class t> typename Foo<t>::Bar Foo<t>::x;

g++4.0.0 then accepts it.

-matt


Okay, that works, but the whole reason I'm doing this is to use Bar as a
class constructor for the various instantiations of Foo<>. If I have to
explicitly define an instance of each instantiation of Foo<> and call a
method on each, then there's no point of using a class constructor at
all. It also makes my code a lot less extensible.

Does anyone know any better ways to write class contstructors for
template classes?

Rennie
Dec 30 '05 #8
mlimber wrote:
Rennie deGraaf wrote:
I'm writing a class similar to this:

#include <iostream>
using namespace std;

template<class t> class Foo
{
private:
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}
};
static Bar x;
t y;
};

template<> Foo<int>::Bar Foo<int>::x;

int main()
{
return 0;
}

When executed, it should print "hello, world" to the console, which it
does when compiled with Sun's CC compiler. However, it does nothing
when compiled with GCC (versions 4.0.2 and older). GCC-compiled
versions produce the expected output when Foo is made into a normal,
rather than template, class, or when Foo::x is made into a pointer and
initialized with a dynamically-allocated object. Is this a bug in GCC,
or one of those poorly-specified edge cases in C++?

Rennie


We discussed a similar problem in this thread (see especially the posts
by James Kanze):

http://groups.google.com/group/comp....48a992ba350f2f

In essence, though GCC's is not the behavior you want, it is the more
standard-conformant compiler on this point, and Sun is incorrect. The
static member x should not be instantiated unless it is actually
referenced, which it is not in your sample program. You can force
instantiation on a conforming compiler by adding a trivial reference to
x somewhere, e.g. in the destructor for Foo<> with something like this:

~Foo() { (void)&x; }

Cheers! --M


On second thought, I'm not sure that this is the same scenario since
you are explicitly specializing Foo.

M

Dec 30 '05 #9
Rennie deGraaf wrote:
Matteo wrote:
Rennie deGraaf wrote:
AD wrote:

I made slight modifications to your program and it worked.
a) I changed the initialisation of static member of template class Foo
as following:
"template<class t> Foo<t>::Bar Foo<t>::x;"
This initializes x for all typenames and not only int.
b) I added a function to class Bar and then used x in Foo to call this
function.
This caused x to be instantiated and Bar constructor was called. This
is explained by concept that template members are initialised at the
first point of use in program and not necessarily at the
definition/declaration. So mere declaration/definition of static member
of template class wont instantiate it.

Following is the changed program and it worked with g++ compiler.

#include <iostream>
using namespace std;

template<class t> class Foo
{
class Bar
{
public:
Bar()
{
cout << "hello, world" << endl;
}

void Call()
{
cout<<"Bar::Call"<<endl;
}
};
public:
static Bar x;
t y;

};

template<class t> Foo<t>::Bar Foo<t>::x;

int main()
{
Foo<int> f;
Foo<int>::x.Call();

return 0;
}
/**************************/
g++ 4.0.2 throws the following error on that code (although g++ 2.95.3
accepts it):

test.cpp:25: error: expected constructor, destructor, or type conversion
before 'Foo'

Rennie

I believe you need to declare Foo<t>::Bar as a typename, like so:
template<class t> typename Foo<t>::Bar Foo<t>::x;

g++4.0.0 then accepts it.

-matt


Okay, that works, but the whole reason I'm doing this is to use Bar as a
class constructor for the various instantiations of Foo<>. If I have to
explicitly define an instance of each instantiation of Foo<> and call a
method on each, then there's no point of using a class constructor at
all. It also makes my code a lot less extensible.

Does anyone know any better ways to write class contstructors for
template classes?

Rennie


See my other response. It may have what you need.

Cheers! --M

Jan 3 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

25 posts views Thread by John Harrison | last post: by
7 posts views Thread by Drew McCormack | last post: by
8 posts views Thread by Scott J. McCaughrin | last post: by
4 posts views Thread by Skybuck Flying | last post: by
26 posts views Thread by Cliff Williams | last post: by
1 post views Thread by CARIGAR | last post: by
2 posts views Thread by Marin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.