473,382 Members | 1,705 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,382 software developers and data experts.

Counting template classes at compile time

Dear all,

I just wondered if it is possible to count the number of classes created via
a template class at compile time.

To show what I mean I post an example, which is not working but carries the
idea:

static int counter = 0; // this variable can be changed only at runtime...
template <typename T> struct want_to_be_counted;
{
static const int help_counting = counter++; // so this is always 0 (or
even better undefined?)
};

Each time when the compiler creates class with a new type, it shall
increment a variable.

want_to_be_counted< int > ----> counter = 1;
want_to_be_counted< float > ----> counter = 2;
want_to_be_counted< int > ----> counter = still 2;

Any ideas or hints where to read? Thank you,
Patrick
Jul 22 '05 #1
7 5924
Patrick Kowalzick wrote:
I just wondered if it is possible to count the number of classes created via
a template class at compile time.
Why would anybody care about that? Why do _you_ care? How would you
use the counter value if it were available?
To show what I mean I post an example, which is not working but carries the
idea:

static int counter = 0; // this variable can be changed only at runtime...
template <typename T> struct want_to_be_counted;
{
static const int help_counting = counter++; // so this is always 0 (or
even better undefined?)
Static members of templates are not instantiated until they are used.
So, you have to use that member in order to cause its instantiation.
};

Each time when the compiler creates class with a new type, it shall
increment a variable.

want_to_be_counted< int > ----> counter = 1;
want_to_be_counted< float > ----> counter = 2;
want_to_be_counted< int > ----> counter = still 2;

Any ideas or hints where to read? Thank you,


I don't think it's possible. Instantiation of a template is a compile-
time activity, and any particular template can be instantiated in more
than one compilation unit, the compiler cannot really keep track of
anything across compilation units, now, can it?

Victor
Jul 22 '05 #2
Hello Victor,

thanks for your response.
Why do _you_ care? How would you
use the counter value if it were available?
Sorry long answer, but you asked why _I_ would care ;).

I am searching a neat possibility to do some multi-dispatching. My
dispatcher right now has some disadvantages and I am trying to correct some
small things and learn about other possibilities. An example for my
implementation later.

I know that Andrei Alexandrescu has developed a very nice one for LOKI, but
there are some reasons why I do not use it. One reason is that I do not want
to use this library (what reasons ever). Besides that it would need too much
adaption to really fit it for my purpose. The best fitting scheme would be
the brute force solution.

Anyway, I want to avoid to put inside the classes the dispatching via
chained calls of virtual functions to keep the orthogonality of my design.
(Similar to Andrei's solution).

Furthermore I want to avoid the RTTI stuff, because in my case I can use
real brute force routines. I know all the branches needed in advance. I use
a switch because it is much faster then nested if's (sure, depending on the
number of classes/combinations) .

An example might look like this:

#include <iostream>
#include <vector>

// forward declaration
struct A;
struct B;

// definig a class with an ID inside to
// avoid the RTTI-processes
template <typename> struct CID;

template <> struct CID<A>
{
static const int ID = 0;
};

template <> struct CID<B>
{
static const int ID = 1;
};

// The class hierachy
struct BASE {
virtual const int ID() = 0;
virtual ~BASE() {}
};

struct A : public BASE
{
void calling() {
std::cout << "A calling" << std::endl;
}
virtual const int ID() {
return CID<A>::ID;
}
};

struct B : public BASE
{
void calling() {
std::cout << "B calling" << std::endl;
}
virtual const int ID() {
return CID<B>::ID;
}
};

// this is an example why I do not like this approach
// for each T i MUST provide the corresponding CID< C<T> >
template <typename T>
struct C : public BASE
{
void calling() {
std::cout << "B calling" << std::endl;
}
virtual const int ID() {
return CID< C<T> >::ID;
}
};

int main()
{
// create collection
std::vector< BASE * > vec;
vec.push_back( new A() );
vec.push_back( new B() );
vec.push_back( new B() );
vec.push_back( new A() );

// example for single dispatch
for (unsigned int i = 0; i < vec.size(); ++i)
switch( vec[i]->ID() )
{
// using here some (not-)nice Makro tricks
case( CID<A>::ID ) :
static_cast<A *>( vec[i] )->calling();
break;
case( CID<B>::ID ) :
static_cast<B *>( vec[i] )->calling();
break;
default :
std::cerr << "Something is wrong...." << std::endl;
}

// cleanup when virtual dtor, otherwise switchtable again
for (unsigned int i = 0; i < vec.size(); ++i) delete vec[i];

return 0;
}

Each class put in the dispatcher must have an ID, accessible via a virtual
call. So far no problem, but coming back to my OP. I wanted to get a class
CID<T> returning a unique ID for each class - automatically:

template <typename T> struct CID;
{
static const int ID = unique_ID<T>();
};

It is similar to a type_info but returning something what could be used
easily in a switch statement.
To show what I mean I post an example, which is not working but carries the idea:

static int counter = 0; // this variable can be changed only at runtime... template <typename T> struct want_to_be_counted;
{
static const int help_counting = counter++; // so this is always 0 (or even better undefined?)


to count the different class types, seemed one solution to me. Anyway it
would be nice to get them in order, for a better efficiency of the switch.
I don't think it's possible. Instantiation of a template is a compile-
time activity, and any particular template can be instantiated in more
than one compilation unit, the compiler cannot really keep track of
anything across compilation units, now, can it?


IMO no problem here.

Regards,
Patrick
Jul 22 '05 #3
Patrick Kowalzick wrote:
Why do _you_ care? How would you
use the counter value if it were available?

Sorry long answer, but you asked why _I_ would care ;).

[...]
It is similar to a type_info but returning something what could be used
easily in a switch statement.


Why does it have to be a switch statement? Couldn't it be, say,
a 'map<whatever, function_pointer>'? 'whatever' could be a string
or something else.

The bottom line is that if you relax the requirement to do it in
compile-time and allow it to be done in run-time, you could get
more and easier solutions.
[...]
I don't think it's possible. Instantiation of a template is a compile-
time activity, and any particular template can be instantiated in more
than one compilation unit, the compiler cannot really keep track of
anything across compilation units, now, can it?

IMO no problem here.


I don't understand your "no problem here" statement.

Victor
Jul 22 '05 #4

"Patrick Kowalzick" <Pa***************@cern.ch> wrote in message
news:ci**********@sunnews.cern.ch...
Dear all,

I just wondered if it is possible to count the number of classes created via
a template class at compile time.


See the thread "instantiation_count (was: is_incomplete)" from the Boost
developers list.

http://lists.boost.org/MailArchives/boost/msg37791.php

Jonathan
Jul 22 '05 #5
Dear Jonathan,
I just wondered if it is possible to count the number of classes created via a template class at compile time.


See the thread "instantiation_count (was: is_incomplete)" from the Boost
developers list.

http://lists.boost.org/MailArchives/boost/msg37791.php


this was exactly what I was searching for. I searched the actual boost but
can not find an actual version of "instantiation_count" or "is_incomplete".
Together with the discussion in the thread mentioned, I believe there is not
yet a tidy solution.

So I will discard this idea for now.

Thanks a lot,
Patrick
Jul 22 '05 #6
Hello Victor
It is similar to a type_info but returning something what could be used
easily in a switch statement.
Why does it have to be a switch statement? Couldn't it be, say,
a 'map<whatever, function_pointer>'? 'whatever' could be a string
or something else.


It must not be a switch, and I will keep in mind that a map might be a
possible solution to replace a switch.

In this case "whatever" should be a type_info (or the string name out of
typeinfo), what IMO is the only unique "feature" for any class. It seems
quite expensive to me to carry around the type_info so I would prefer, e.g.
an int. With an int I could use either switch, map (Alexandrescus
BasicDispatcher) or vector (Alexandrescus BasicFastDispatcher).

I did not test yet, but with map it should be _possible_ to use the
type_info (oh - I have to look if it is comparable). Anyway, all the
structures mentioned above must be 2D for double-dispatching, means
nested-ifs, nested switch/if, 2D-map or 2D-vector/matrix.
The bottom line is that if you relax the requirement to do it in
compile-time and allow it to be done in run-time, you could get
more and easier solutions.


This indeed might be true, but like described in my OP I reduce it to
"how-to get a unique ID", what is independent which structure to take.
Alexandrescu for example is defining a macro which must be included in each
class dispatched by the BasicFastDispatcher to define this ID.

// Andrei Alexandrescus Macro
#define IMPLEMENT_INDEXABLE_CLASS(SomeClass) \
static int& GetClassIndexStatic() \
{\
static int index = -1;\
return index;\
}\
virtual int& GetClassIndex()\
{\
assert(typeid(*this) == typeid(SomeClass));\
return GetClassIndexStatic();\
}

The variable index is used to indicate if the class was used in a dipatcher
and if, which slot was used. This is working quite nice and putting together
a single-dispatcher could look like this:

template <typename T>
void Add(std::vector<void(*)(const BASE &)> & callbacks)
{
int& index = T::GetClassIndexStatic();
if (index < 0) index = callbacks.size(); // define slot where to go
if ( callbacks.size() < index + 1 ) callbacks.resize( index + 1 ); //
assure that vector is big enough
void(* fooT)( const T & ) = foo;
callbacks[index] = (void(*)(const BASE &))fooT;
}

//the calls somewhere

std::vector<void(*)(const BASE &)> callbacks;

Add<A>(callbacks);
Add<B>(callbacks);

for (unsigned int i = 0; i < vec.size(); ++i)
{
callbacks[vec[i]->GetClassIndex()](*vec[i]);
}
So I still search a solution to define an ID, but I think I will refine
Alexandrescus method and adopt it to my needs.

Thanks,
Patrick
Jul 22 '05 #7

"Patrick Kowalzick" <Pa***************@cern.ch> wrote in message
news:ci**********@sunnews.cern.ch...
Dear Jonathan,
I just wondered if it is possible to count the number of classes created via a template class at compile time.


See the thread "instantiation_count (was: is_incomplete)" from the Boost
developers list.

http://lists.boost.org/MailArchives/boost/msg37791.php


this was exactly what I was searching for. I searched the actual boost but
can not find an actual version of "instantiation_count" or "is_incomplete".
Together with the discussion in the thread mentioned, I believe there is not
yet a tidy solution.


I think the consensus was that it's not possible with a standard-conforming
compiler.

Jonathan
Jul 22 '05 #8

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

Similar topics

2
by: arch | last post by:
Hi, I am trying to implement a class hierarchy where there will be a base class defining the interface and some common operations (interface+implentation): Constraints : no STL. This will be...
1
by: Oplec | last post by:
Hi, I'm learning C++ as a hobby using The C++ Programming Language : Special Edition by Bjarne Stroustrup. I'm working on chpater 13 exercises that deal with templates. Exercise 13.9 asks for me...
1
by: suranap | last post by:
I am looking at some examples of template metaprogramming, but I'm not clear on some details of templates. In particular, what kinds of computations will be performed at compile-time? Is it only...
8
by: Tony Johansson | last post by:
Hello Experts! What does this mean actually. If you have a template with a type and non-type template argument, say, like this template<typename T, int a> class Array {. . .}; then A<int,...
3
by: Yohan | last post by:
Hello, I have a question concerning the template classes and their parameters. Is it possible to set a condition on the template parameters in a way that could block the compilation if the...
9
by: jc | last post by:
Hi all, I have a data type to use that I can't modify its codes. E.g. This template data type is data_type. When I declare a variable of this data_type, I write as following: data_type(8,...
7
by: mathieu | last post by:
Hello, I did read the FAQ on template(*), since I could not find an answer to my current issue I am posting here. I have tried to summarize my issue in the following code (**). Basically I am...
5
by: Wayne Shu | last post by:
Hi, guys I am reading Vandevoorde and Josuttis 's "C++ Template The Complete Guide" these days. When I read the chapter 15: Traits and Policy classes. I copy the code in 15.2.2 that use to...
4
by: suman.nandan | last post by:
Hi C++ Experts ! I have a little weird requirement. I have a base class, say B and lots of classes D1 .. Dn publicly derived from it. Over the course of development the number of derived...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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...

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.