Enforcing behaviour in derived classes (C++)

Started by
22 comments, last by Shadowdancer 20 years, 11 months ago
Well, I have a question. If all you want is a static id per class instance, and you aren't adverse to something like this:

class derived : public base < derived > {};

You dont' need to implement _anything_ involved w/ RTTI, but you don't get a string constant. If you aren't adverse to a macro, then you can get a string.

It's creative meta-macro-programming, as MKH said. It's pretty nifty, I like it... and the ID is even at compile time. Useful. But ...probably not for you .
Anyway, if you want it, just post. I think it even works on MSVC6 (gasp).

[edited by - risingdragon3 on May 5, 2003 4:29:14 PM]

[edited by - risingdragon3 on May 5, 2003 4:29:42 PM]
Advertisement
Hmm... but doesn''t that mean you can''t do virtual functions/polymorphism, since each derived class would inherit from a different specialization of the base class?

How appropriate. You fight like a cow.
Well, I was imagining that the template would be defined like this:

      #include <iostream>#include <conio.h>namespace aux {template <int n> struct size_ret {    char size[n+2];};size_ret<-1> series(...);template <class T,int n> struct get_and_inc;template <bool can> struct helper;template <> struct helper<true> {    template <class T,int n> struct impl {        enum {value = n};        friend size_ret<n+1> series(size_ret<n>*);    };};template <> struct helper<false> {    template <class T,int n> struct impl {        enum {value = get_and_inc<T,n+1>::value};    };};template <class T,int n> struct get_and_inc {    enum {current_value = sizeof(series((size_ret<n>*)0))-2};    enum {is_null = current_value == -1};    enum {value = helper<is_null>::template impl<T,n>::value};};}//assumes base_type is your "true" basestruct base_type {virtual const int get_id() = 0;};template <class child_type> class base : public base_type {enum {ID = aux::get_and_inc<child_type,0>::value};virtual const int get_id() {return ID;}};struct child_a : public base<child_a> {};struct child_b : public base<child_b> {};using namespace std;int main() {base_type* ptr = new child_a;cout << ptr->get_id();delete ptr;ptr = new child_b;cout << ptr->get_id();delete ptr;getch();}      



...useful? I dunno. but definitely cool

EDIT: silly ;'s
EDIT2: Of course you would have to edit the recursive template to nibble at the recursion, this is not "industrial strength": depending on your compiler, you may hit the template recursive limit if you define more then say 60 types. If you nibble you can get as many as you want.
[edited by - risingdragon3 on May 5, 2003 4:41:43 PM]

[edited by - risingdragon3 on May 5, 2003 4:43:04 PM]
I just realized that you can also check at compile time to see how many derived classes you have declared:

  template <bool can> struct get_helper;template <> struct get_helper<true> {    template <class T,int n> struct impl {        enum {value = n};    };};template <> struct get_helper<false> {    template <class T,int n> struct impl {        enum {value = get_and_inc<T,n+1>::value};    };};template <class T,int n> struct get {    enum {current_value = sizeof(series((size_ret<n>*)0))-2};    enum {is_null = current_value == -1};    enum {value = get_helper<is_null>::template impl<T,n>::value};};  


Interesting. This is like compile time variables, in a way. Hmmm...could I do subtraction?..I don''t think that''s possible...wait...yes..i could...
*tests*...I''ll report back.

This topic is closed to new replies.

Advertisement