Counting template classes at compile time

Discussion in 'C++' started by Patrick Kowalzick, Sep 15, 2004.

  1. 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
     
    Patrick Kowalzick, Sep 15, 2004
    #1
    1. Advertising

  2. 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
     
    Victor Bazarov, Sep 15, 2004
    #2
    1. Advertising

  3. 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->ID() )
    {
    // using here some (not-)nice Makro tricks
    case( CID<A>::ID ) :
    static_cast<A *>( vec )->calling();
    break;
    case( CID<B>::ID ) :
    static_cast<B *>( vec )->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;

    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
     
    Patrick Kowalzick, Sep 15, 2004
    #3
  4. 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
     
    Victor Bazarov, Sep 15, 2004
    #4
  5. "Patrick Kowalzick" <> wrote in message
    news:ci8s6i$pnt$...
    > 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
     
    Jonathan Turkanis, Sep 15, 2004
    #5
  6. 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
     
    Patrick Kowalzick, Sep 16, 2004
    #6
  7. 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->GetClassIndex()](*vec);
    }


    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
     
    Patrick Kowalzick, Sep 16, 2004
    #7
  8. "Patrick Kowalzick" <> wrote in message
    news:cibi08$bjn$...
    > 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
     
    Jonathan Turkanis, Sep 16, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. flamesrock
    Replies:
    8
    Views:
    502
    Hendrik van Rooyen
    Nov 24, 2006
  2. Replies:
    4
    Views:
    335
    Victor Bazarov
    Apr 10, 2006
  3. Nagaraj
    Replies:
    1
    Views:
    892
    Lionel B
    Mar 1, 2007
  4. Carter
    Replies:
    2
    Views:
    518
    Carter
    Mar 4, 2009
  5. edwardfredriks

    counting up instead of counting down

    edwardfredriks, Sep 6, 2005, in forum: Javascript
    Replies:
    6
    Views:
    213
    Dr John Stockton
    Sep 7, 2005
Loading...

Share This Page