473,785 Members | 2,720 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

static members of template classes optimized away?

Hello,

this is a test case of something I just can't explain myself:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <list>
typedef void (*registerfunc) ();

class CMgr
{
public:
static std::list<regis terfunc> & GetRegisterList ()
{
static std::list<regis terfunc> registerlist;
return registerlist;
}

static bool Register(regist erfunc func)
{
GetRegisterList ().push_back(fu nc);
return true;
}

};

template< class T> class THelper
{
public:
//virtual bool GetDummy() { return ms_bDummy; }

private:
static bool ms_bDummy;
};

template <class T>
bool THelper<T>::ms_ bDummy=CMgr::Re gister(T::Regis ter);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registe ring CTest\n");
}
};

int main(const char * args[], int iNumArgs)
{
printf("There are %d functions registered.\n",
CMgr::GetRegist erList().size() );

return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7

I just want a list of functions be generated when the program starts
up. The output of the program is the following:

Optimizations turned off:
"There are 0 functions registered."

Optimizations turned off and "GetDummy() " uncommented in THelper:
"There are 1 functions registered."

Leaving "GetDummy() " uncommented and turing optimizations on:
"There are 0 functions registered."

Instanciating CTest and calling GetDummy() from main():
"There are 1 functions registered."

I cannot explain this to me. When is the compiler optimizing away the
static member and not performing initialization?

Thanks a lot.

Markus

Feb 14 '06 #1
8 2842

Markus Henschel wrote:
Hello,

this is a test case of something I just can't explain myself:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <list>
typedef void (*registerfunc) ();

class CMgr
{
public:
static std::list<regis terfunc> & GetRegisterList ()
{
static std::list<regis terfunc> registerlist;
return registerlist;
}

static bool Register(regist erfunc func)
{
GetRegisterList ().push_back(fu nc);
return true;
}

};

template< class T> class THelper
{
public:
//virtual bool GetDummy() { return ms_bDummy; }

private:
static bool ms_bDummy;
};

template <class T>
bool THelper<T>::ms_ bDummy=CMgr::Re gister(T::Regis ter);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registe ring CTest\n");
}
};

int main(const char * args[], int iNumArgs)
{
printf("There are %d functions registered.\n",
CMgr::GetRegist erList().size() );

return 0;
}


Members of templates are instantiated on demand. As long as nothing in
the code accesses THelper<T>::ms_ bDummy it does not get instantiated.

Feb 14 '06 #2
Right. When I uncomment the virtual function accessing ms_bDummy the
static member is initialized. But optimizations make the compiler
remove GetDummy because it is never called and this in turn removes the
static member. But shouldn't the compiler know that the function that
initializes m_bDummy is changing other variables that ARE accessed?

I had this idea of executing initialization time code from an article
about a property system. I checked it again and the only difference to
my code is that I use a bool as static member but the article used a
property struct. So I made some changes to the example code:

////////////////////////////////
template< class T> class THelper
{
public:
virtual bool GetDummy() { return ms_Dummy.m_bTes t; }
static CDummy ms_Dummy;
};

template <class T>
CDummy THelper<T>::ms_ Dummy=CMgr::Reg ister(T::Regist er);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registe ring CTest\n");
}
};
//////////////////////////////////

This way the output is always: "There are 1 functions registerd." Can I
rely on this or is this just because the compiler isn't smart enough to
remove the GetDummy() member function?

Feb 14 '06 #3

Markus Henschel wrote:
Right. When I uncomment the virtual function accessing ms_bDummy the
static member is initialized. But optimizations make the compiler
remove GetDummy because it is never called and this in turn removes the
static member. But shouldn't the compiler know that the function that
initializes m_bDummy is changing other variables that ARE accessed?

I had this idea of executing initialization time code from an article
about a property system. I checked it again and the only difference to
my code is that I use a bool as static member but the article used a
property struct. So I made some changes to the example code:
[]
This way the output is always: "There are 1 functions registerd." Can I
rely on this or is this just because the compiler isn't smart enough to
remove the GetDummy() member function?


You can make your code more reliable by simplifying it.

First, I got rid of std::list<> and replaced it with a custom list
which only requires static initialization and thus is not prone to the
order of dynamic initialization between modules problem. You can
declare an extern object of this class in a header and safely use it
from constructors of global objects. Also, the list is intrusive, so
that it does not require dynamic allocations.

Second, I add elements into the list by declaring global (or namespace
scope) objects of a class. Its constructor adds it into the list and
this can not be optimized out.

struct registrations
{
struct node
{
void(*fn)();
node* next;
};

void push_front(node * n)
{
n->next = head_;
head_ = n;
}

void invoke_all()
{
for(node* n = head_; n; n = n->next)
n->fn();
}

node* head_;
} l = {};

template<void(* FN)()>
struct do_register : registrations:: node
{
do_register()
{
this->fn = FN;
l.push_front(th is);
}
};

struct some
{
static void register_fn() { printf("%s\n", __PRETTY_FUNCTI ON__); }
};

do_register<som e::register_fn> const register_some;

int main()
{
l.invoke_all();
}

Feb 14 '06 #4
Thanks. So it is not possible to somehow force the initialization of
static members that are not used? It is just out if interest as your
solution of manually registering classes by filling a header file is
just slightly more work but offers more flexibility.

Feb 14 '06 #5

Markus Henschel wrote:
Thanks. So it is not possible to somehow force the initialization of
static members that are not used?


Just take its address.

class CTest : public THelper<CTest>
{
public:
static void Register()
{
void* p = &THelper<CTest> ::ms_Dummy; (void)p;
printf("Registe ring CTest\n");
}
};

Feb 14 '06 #6
Markus Henschel wrote:
Hello,

this is a test case of something I just can't explain myself:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <list>
typedef void (*registerfunc) ();

class CMgr
{
public:
static std::list<regis terfunc> & GetRegisterList ()
{
static std::list<regis terfunc> registerlist;
return registerlist;
}

static bool Register(regist erfunc func)
{
GetRegisterList ().push_back(fu nc);
return true;
}

};

template< class T> class THelper
{
public:
//virtual bool GetDummy() { return ms_bDummy; }

private:
static bool ms_bDummy;
};

template <class T>
bool THelper<T>::ms_ bDummy=CMgr::Re gister(T::Regis ter);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registe ring CTest\n");
}
};

int main(const char * args[], int iNumArgs)
{
printf("There are %d functions registered.\n",
CMgr::GetRegist erList().size() );

return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7

I just want a list of functions be generated when the program starts
up. The output of the program is the following:

Optimizations turned off:
"There are 0 functions registered."
Ok. CTest forces THelper<CTest> to instantiate. But non of the member of
THelper<CTest> ever gets used so they are not instantiated. Therefore no
function registration.

Optimizations turned off and "GetDummy() " uncommented in THelper:
"There are 1 functions registered."
Now CTest again forces THelper<CTest> to instantiate. CTest also opens a
chance for other types which inherits CTest to override the virtual
function THelper<CTest>: :GetDummy, and that forces
THelper<CTest>: :GetDummy to instantiate, which in turn instantiates
THelper<CTest>: :ms_bDummy, which gets CTest::register registered.

Leaving "GetDummy() " uncommented and turing optimizations on:
"There are 0 functions registered."
Now the compiler performs whole program optimization and finds out that
the virtual function is never ever used, so optimized it off, taking
ms_bDummy down with it.

The compiler is gonna opt it away even if you explicitly instantiate it
because the optimization happens after all template instantiation. :)

Instanciating CTest and calling GetDummy() from main():
"There are 1 functions registered."
Well if you use GetDummy() then the optimizer of course can't optimize
it off.

I cannot explain this to me. When is the compiler optimizing away the
static member and not performing initialization?
Because it is allowed to optimize away entities that are not used
through out the program. Your trick to register is consider a side
effect and is therefore ignored.

Thanks a lot.

Markus

Regards,
Ben
Feb 14 '06 #7
What does the above (void)p do?

What I really wanted was to be able to execute code automatically at
program startup so it's sufficient to just write a class and it will
automatically insert a classinfo struct into a global list that can be
browsed at runtime. The struct would contain a factory function. So a
class instance can be created without knowing the class.

By deriving from a class template a static member of type struct
classinfo is added to the class. In the constructor of classinfo I
added a pointer to it to a global list.

The problem I'm facing is that the static struct might not be
initialized and created if the class itself is not really used.

Feb 14 '06 #8
> Just take its address.

class CTest : public THelper<CTest>
{
public:
static void Register()
{
void* p = &THelper<CTest> ::ms_Dummy; (void)p;
printf("Registe ring CTest\n");
}
};


This won't work. Guess what? THelper<CTest> IS instantiated. But hey
hello optimizer takes away its members after it is instantiated.

If your optimizer is powerful enough you can actually use
THelper<CTest>: :GetDummy in main and still no function gets registered. :)

In my case I need to actually write into THelper<CTest>: :ms_dDummy to
get what the OP desires to:

int main(const char * args[], int iNumArgs)
{
CTest t;
t.ms_bDummy = true; // bust the optimizer

printf("There are %d functions registered.\n",
CMgr::GetRegist erList().size() );

return 0;
}

Regards,
Ben
Feb 14 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1632
by: Alibek | last post by:
Hello ! I have here template class with static members. and I put definition of the static member in the same ..h file where the class was declared. however, we are getting very stange errors, because static member occupy same place as some other non-static variables. and so application crashes. compiler somehow allocates same place for them.
5
2063
by: Thomas Matthews | last post by:
Hi, I have three classes: Category Author Publisher Each of these classes stores its information into a database table of <ID, text>. (They are fields that have a foreign key.) There is only one table for each instance of these classes (IOW,
18
5768
by: Erik Arner | last post by:
Hi, I really need some help here. After upgrading to g++ 3.4 I have run into all sorts of troubles that I'm sure depends on my lack of proper understanding of C++. I would now like to get it right once and for all, if possible. Most severe is the problem illustrated by the code below. It's based on the "pluggable factory pattern" described in http://www.adtmag.com/joop/crarticle.asp?ID=1520
8
1640
by: Jon Slaughter | last post by:
Is there any way to declare a member of a base class to make the itself in the derived class to be static? i.e., I have two classes class Base { protected: char *name;
13
7735
by: Adam H. Peterson | last post by:
I just made an observation and I wondered if it's generally known (or if I'm missing something). My observation is that static protected members are essentially useless, only a hint to the user. They don't actually protect any encapsulation or anything, and for all the actual protection they offer, they might as well be public. For example: class B { protected:
3
5711
by: Diebels | last post by:
Hi, I have some problems using static variables which results in a core dump. I have attached code and coredump to the end of my message. I am trying to implement a kind of factory design. I have a base class with several sub classes. In runtime I want to create a instance of a sub class and assign it to a base class pointer. Nothing fancy about that. I also want to be able in runtime to decide witch type of sub class that is to be...
5
11326
by: John Goche | last post by:
Hello, I would like to know whethere there is a difference between a const variable and a static const variable inside a class. After all, if a variable is const in a class, the compiler can always optimize and turn it into a static const variable to save runtim memory/stack space since being const it cannot be changed. (?) Thanks,
272
14190
by: Peter Olcott | last post by:
http://groups.google.com/group/comp.lang.c++/msg/a9092f0f6c9bf13a I think that the operator() member function does not work correctly, does anyone else know how to make a template for making two dimensional arrays from std::vectors ??? I want to use normal Array Syntax.
17
8384
by: Juha Nieminen | last post by:
As we know, the keyword "inline" is a bit misleading because its meaning has changed in practice. In most modern compilers it has completely lost its meaning of "a hint for the compiler to inline the function if possible" (because if the compiler has the function definition available at an instantiation point, it will estimate whether to inline it or not, and do so if it estimates it would be beneficial, completely regardless of whether...
0
10319
Oralloy
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...
0
10147
jinu1996
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...
0
9947
tracyyun
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...
1
7496
isladogs
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...
0
6737
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();...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4046
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3645
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2877
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.