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 9 1510
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
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<c lass 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::Cal l"<<endl;
}
};
public:
static Bar x;
t y;
};
template<class t> Foo<t>::Bar Foo<t>::x;
int main()
{
Foo<int> f;
Foo<int>::x.Cal l();
return 0;
}
/*************** ***********/
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
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<c lass 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::Cal l"<<endl; } }; public: static Bar x; t y;
};
template<class t> Foo<t>::Bar Foo<t>::x;
int main() { Foo<int> f; Foo<int>::x.Cal l();
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
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<c lass 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::Cal l"<<endl; } }; public: static Bar x; t y;
};
template<class t> Foo<t>::Bar Foo<t>::x;
int main() { Foo<int> f; Foo<int>::x.Cal l();
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
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
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<cl ass 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<cla ss t> class Foo { class Bar { public: Bar() { cout << "hello, world" << endl; }
void Call() { cout<<"Bar::Cal l"<<endl; } }; public: static Bar x; t y;
};
template<cla ss t> Foo<t>::Bar Foo<t>::x;
int main() { Foo<int> f; Foo<int>::x.Cal l();
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
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
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<cl ass 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<cla ss t> class Foo { class Bar { public: Bar() { cout << "hello, world" << endl; }
void Call() { cout<<"Bar::Cal l"<<endl; } }; public: static Bar x; t y;
};
template<cla ss t> Foo<t>::Bar Foo<t>::x;
int main() { Foo<int> f; Foo<int>::x.Cal l();
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: John Harrison |
last post by:
This code fails to compile on Comeau C++ and VC++ 7.1 (with language
extensions disabled)
template <class T>
struct B
{
T b;
};
template <class T>
|
by: Drew McCormack |
last post by:
I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:
template <typename T>
class M {
static Registrar<M> registrar;
};
The constructor of Registrar does the registering when it is initialized.
|
by: CoolPint |
last post by:
I would be grateful if someone could point out if I am understanding
correctly and suggest ways to improve. Sorry for the long message and
I hope you will kindly bear with it. I have to make it elaborate to
make sure my questions are clear enough.
Let's say I need to write a function whose logic is same for all types
(T) except in the case of T * (including const T *). Furtheremore ,
the function needs to be written differently for...
|
by: Scott J. McCaughrin |
last post by:
The following program compiles fine but elicits this message from the
linker: "undefined reference to VarArray::funct" and thus fails.
It seems to behave as if the static data-member: VarArray::funct were
an extern, but it is declared in the same file (q.v.). What is the
remedy for this?
=================
|
by: Skybuck Flying |
last post by:
Hello,
I have a question about the C language.
This piece of code is from the glibc library.
My question is about the static struct
The question is....
| |
by: Dale |
last post by:
Is it possible to declare a method of an interface as static?
For instance, can I create an interface that defines a static method and 2
instance methods?
|
by: Cliff Williams |
last post by:
Can someone explain the pros/cons of these different ways of creating a
class?
// 1
function myclass() {
this.foo1 = function() {...}
}
// 2a
|
by: mike b |
last post by:
Hello everyone, thanks in advance for your help. I'm new to C++
templates and have run into some issues using member function
templates. I have a shared library containing templates that I'm
trying to use from an executable, compile using gcc 4.1.2. Everything
works fine until I try specializing one of the static member function
templates in a non-template class. I have a feeling I'm messing up
something obvious so before I post a...
|
by: Jeffrey |
last post by:
My understanding is that if you write
class X {
int y;
static int z;
};
then you've defined (and declared) X and y, but you have only declared
(and not defined) z. If you'd like to actually define z, you also
need to add
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |