473,396 Members | 2,154 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

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<registerfunc> & GetRegisterList()
{
static std::list<registerfunc> registerlist;
return registerlist;
}

static bool Register(registerfunc func)
{
GetRegisterList().push_back(func);
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::Register(T::Register);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registering CTest\n");
}
};

int main(const char * args[], int iNumArgs)
{
printf("There are %d functions registered.\n",
CMgr::GetRegisterList().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 2823

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<registerfunc> & GetRegisterList()
{
static std::list<registerfunc> registerlist;
return registerlist;
}

static bool Register(registerfunc func)
{
GetRegisterList().push_back(func);
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::Register(T::Register);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registering CTest\n");
}
};

int main(const char * args[], int iNumArgs)
{
printf("There are %d functions registered.\n",
CMgr::GetRegisterList().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_bTest; }
static CDummy ms_Dummy;
};

template <class T>
CDummy THelper<T>::ms_Dummy=CMgr::Register(T::Register);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registering 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(this);
}
};

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

do_register<some::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("Registering 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<registerfunc> & GetRegisterList()
{
static std::list<registerfunc> registerlist;
return registerlist;
}

static bool Register(registerfunc func)
{
GetRegisterList().push_back(func);
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::Register(T::Register);
class CTest : public THelper<CTest>
{
public:
static void Register()
{
printf("Registering CTest\n");
}
};

int main(const char * args[], int iNumArgs)
{
printf("There are %d functions registered.\n",
CMgr::GetRegisterList().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("Registering 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::GetRegisterList().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
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...
5
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...
18
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...
8
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
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. ...
3
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...
5
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...
272
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...
17
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...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
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,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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,...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.