C++ typeof and typeid

This is a small discussion about a solution I posted on stack overflow, related to my need for FAB_LED coding.

I came across the need to compare variable types, while writing my C++ LED library class, because of my reliance on template types. This capability becomes useful when you have a template class which itself defines a template function: The user may set both to the same type or to different types.

If you read through my example, and think of other ways to implement the same thing through simple function polymorphism, you will notice that this solution is more elegant: There is only one code block handling all use cases, which can be automatically specialized/optimized at compile time. It is also efficient, compact, as well as much simpler to maintain.

 C++ shortcomings

  • typeid() (C++ only) is meant to work like sizeof() would, but is apparently a runtime check, which works on classes as they automatically define a type field with a unique type ID. It is implemented also for base types (int, float, etc.). If it doesn’t resolve statically for cases where all the info is known at compile time, it  can’t be used for code optimization, and would be of little use for my arduino library.
  • typeof() seems rather useless to me, except maybe to write contrived C macros with hidden temporary variables. You cannot use it to do a compile-time type check from my attempts. It can only be used as a replacement for a type during a variable declaration.

So the built-in support is not there. Bummer 😦 It would have avoided managing types.

My solution…

I hence forth came up with a hybrid solution, which works in my use case. My structures now all declare a static type field, loaded with a unique value:

class X { static const uint8_t type = 2; ...}

Because it is a static const, it is not allocated with each instance of the class/struct. Once the compiler analyses the code, it also ends up being deleted completely once it’s filled its purpose of guarding unused code blocks.

Now I can use that new static property to handle all my use cases:

template <class TC> class foo {
    private:
    TC * buffer;
    static inline template <class TF> void bar(TF * data) {
        if (data.type == buffer.type) {
            bcopy(data, buffer, ...);
        } else {
            slowConvert(data);
        }
    }

Now I can use that static type property to handle all my use cases:

foo<type1> foo1;

type1 * v1;
type2 * v2;
uint8_t * v3;
foo1.bar<type1>(v1); // replaced by fast bcopy()
foo1.bar<type2>(v2); // replaced by slow convert()
foo1.bar<uint8_t>(v3); // should fail!

Of course as an API this is still very ugly: your template has to declare the type of your input parameter. The next step is to provide a clean API of all types supported by the class. Notice how it becomes simple to support basic types because this circumvents the need to compare those types, using a built-in C++ mechanism for that:

    static inline void bar(rgb * data) { bar<rgb>(data); }
    static inline void bar(bgrw * data) { bar<bgrw>(data); }
    static inline void bar(uint8_t * data) { bar<rgb>((rgb *) data); }

You can now cleanly call the API:

foo1.bar(v1); // replaced by fast bcopy()
foo1.bar(v2); // replaced by slow convert()
foo1.bar(v3); // replaced by fast bcopy()

The user now has no need to worry about his data types unless performance matters for the use case.

 

 
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s