Counting template classes at compile time

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Patrick Kowalzick

    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_coun ted;
    {
    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_coun ted< int > ----> counter = 1;
    want_to_be_coun ted< float > ----> counter = 2;
    want_to_be_coun ted< int > ----> counter = still 2;

    Any ideas or hints where to read? Thank you,
    Patrick


  • Victor Bazarov

    #2
    Re: Counting template classes at compile time

    Patrick Kowalzick wrote:[color=blue]
    > I just wondered if it is possible to count the number of classes created via
    > a template class at compile time.[/color]

    Why would anybody care about that? Why do _you_ care? How would you
    use the counter value if it were available?
    [color=blue]
    > 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_coun ted;
    > {
    > static const int help_counting = counter++; // so this is always 0 (or
    > even better undefined?)[/color]

    Static members of templates are not instantiated until they are used.
    So, you have to use that member in order to cause its instantiation.
    [color=blue]
    > };
    >
    > Each time when the compiler creates class with a new type, it shall
    > increment a variable.
    >
    > want_to_be_coun ted< int > ----> counter = 1;
    > want_to_be_coun ted< float > ----> counter = 2;
    > want_to_be_coun ted< int > ----> counter = still 2;
    >
    > Any ideas or hints where to read? Thank you,[/color]

    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

    Comment

    • Patrick Kowalzick

      #3
      Re: Counting template classes at compile time

      Hello Victor,

      thanks for your response.
      [color=blue]
      > Why do _you_ care? How would you
      > use the counter value if it were available?[/color]

      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.
      [color=blue][color=green]
      > > To show what I mean I post an example, which is not working but carries[/color][/color]
      the[color=blue][color=green]
      > > idea:
      > >
      > > static int counter = 0; // this variable can be changed only at[/color][/color]
      runtime...[color=blue][color=green]
      > > template <typename T> struct want_to_be_coun ted;
      > > {
      > > static const int help_counting = counter++; // so this is always 0[/color][/color]
      (or[color=blue][color=green]
      > > even better undefined?)[/color][/color]

      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.
      [color=blue]
      > 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?[/color]

      IMO no problem here.

      Regards,
      Patrick


      Comment

      • Victor Bazarov

        #4
        Re: Counting template classes at compile time

        Patrick Kowalzick wrote:[color=blue][color=green]
        >>Why do _you_ care? How would you
        >>use the counter value if it were available?[/color]
        >
        >
        > 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.[/color]

        Why does it have to be a switch statement? Couldn't it be, say,
        a 'map<whatever, function_pointe r>'? '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.
        [color=blue]
        > [...][color=green]
        >>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?[/color]
        >
        >
        > IMO no problem here.[/color]

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

        Victor

        Comment

        • Jonathan Turkanis

          #5
          Re: Counting template classes at compile time


          "Patrick Kowalzick" <Patrick.Kowalz ick@cern.ch> wrote in message
          news:ci8s6i$pnt $1@sunnews.cern .ch...[color=blue]
          > Dear all,
          >
          > I just wondered if it is possible to count the number of classes created via
          > a template class at compile time.[/color]

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



          Jonathan


          Comment

          • Patrick Kowalzick

            #6
            Re: Counting template classes at compile time

            Dear Jonathan,
            [color=blue][color=green]
            > > I just wondered if it is possible to count the number of classes created[/color][/color]
            via[color=blue][color=green]
            > > a template class at compile time.[/color]
            >
            > See the thread "instantiation_ count (was: is_incomplete)" from the Boost
            > developers list.
            >
            > http://lists.boost.org/MailArchives/boost/msg37791.php[/color]

            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


            Comment

            • Patrick Kowalzick

              #7
              Re: Counting template classes at compile time

              Hello Victor
              [color=blue][color=green]
              > > It is similar to a type_info but returning something what could be used
              > > easily in a switch statement.[/color]
              >
              > Why does it have to be a switch statement? Couldn't it be, say,
              > a 'map<whatever, function_pointe r>'? 'whatever' could be a string
              > or something else.[/color]

              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 BasicFastDispat cher).

              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.
              [color=blue]
              > 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.[/color]

              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 BasicFastDispat cher to define this ID.

              // Andrei Alexandrescus Macro
              #define IMPLEMENT_INDEX ABLE_CLASS(Some Class) \
              static int& GetClassIndexSt atic() \
              {\
              static int index = -1;\
              return index;\
              }\
              virtual int& GetClassIndex() \
              {\
              assert(typeid(* this) == typeid(SomeClas s));\
              return GetClassIndexSt atic();\
              }

              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(*)(cons t BASE &)> & callbacks)
              {
              int& index = T::GetClassInde xStatic();
              if (index < 0) index = callbacks.size( ); // define slot where to go
              if ( callbacks.size( ) < index + 1 ) callbacks.resiz e( index + 1 ); //
              assure that vector is big enough
              void(* fooT)( const T & ) = foo;
              callbacks[index] = (void(*)(const BASE &))fooT;
              }

              //the calls somewhere

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

              Add<A>(callback s);
              Add<B>(callback s);

              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


              Comment

              • Jonathan Turkanis

                #8
                Re: Counting template classes at compile time


                "Patrick Kowalzick" <Patrick.Kowalz ick@cern.ch> wrote in message
                news:cibi08$bjn $1@sunnews.cern .ch...[color=blue]
                > Dear Jonathan,
                >[color=green][color=darkred]
                > > > I just wondered if it is possible to count the number of classes created[/color][/color]
                > via[color=green][color=darkred]
                > > > a template class at compile time.[/color]
                > >
                > > See the thread "instantiation_ count (was: is_incomplete)" from the Boost
                > > developers list.
                > >
                > > http://lists.boost.org/MailArchives/boost/msg37791.php[/color]
                >
                > 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.[/color]

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

                Jonathan


                Comment

                Working...