Combining GCC typeof () extension with principal access

I am working on a C ++ library that uses static polymorphism via templates. It is designed this way because the target is a small stack embedded system, and it is often useful to use member functions inline

to persist while using the stack.

Using templates for static polymorphism means that the names of the event emitter types (most often device drivers) are often disgusting:

class DeviceThatUsesSPI<class SPI_BUS_TYPE> {

  public:
    class DeviceEvent : public Event<DeviceThatUsesSPI> {};

    // and the rest of the device driver implementation, including
    // the code that emits that event.

}

SomeSpecificGpioBus gpio_bus();
SoftwareSpiBus<typeof(gpio_bus)> spi_bus(&gpio_bus);
DeviceThatUsesSPI<typeof(spi_bus)> device(&spi_bus);

      

As you can see, we are using the GCC extension operator typeof

to avoid having to re-spell the type name many times DeviceThatUsesSPI<SoftwareSpiBus<SomeSpecificGpioBus>>

. It worked like a charm wherever we tried it, until today I tried to use it to access the nested class representing the event. In my current example, this is a custom specialization that implements binding a compile event handler:

template<>
inline void event_handler<typeof(device)::ExampleEvent>(typeof(device) *emitter) {
    // event handler implementation...
}

      

However, I've also tried this in a much more minimal variable declaration example:

typeof(device)::ExampleEvent event;

      

In both cases, g ++ does not parse the syntax error. My guess is that this is because there is no situation in the standard C ++ grammar where ::

it follows anything other than an identifier, and the parser cannot backtrack and treat the first part as a type when it encounters colons.

However, the GCC manualtypeof

makes the following promise about this operator:

Design

A typeof

can be used anywhere a typedef name can be used. For example, you can use it in an ad, in a sheet, or inside sizeof

or typeof

.

If I replace the two uses typeof

in my example with a typedef, g ++ is happy:

typedef typeof(device) device_type;

template<>
inline void event_handler<device_type::ExampleEvent>(typeof(device) *emitter) {
    // event handler implementation...
}

device_type::ExampleEvent event;

      

So this confirms my suspicion that the compiler is fine with what I wrote semantically, but the grammar does not allow me to express it. While using typedef indirection gives me working code, I would rather find a way to make the event handler declarations self-contained for the convenience of users of this library. Is there a way to write a statement typeof

to remove the ambiguity of the parsing so that I can make the event declaration a one-line?

+3


source to share


2 answers


I think a little meta function might do the trick.

template<typename T>
struct self
{
   typedef T type;
};

      

then use it like:

template<>
inline void 
event_handler<self<typeof(device)>::type::ExampleEvent>(typeof(device) *emitter)
{
    // event handler implementation...
}

      

Or you can define a meta-function (which is less general) as:

template<typename T>
struct event
{
   typedef typename T::ExampleEvent type;
};

      



then use it like:

template<>
inline void 
event_handler<event<typeof(device)>::type>(typeof(device) *emitter)
{
    // event handler implementation...
}

      


By the way, in C ++ 11 you can use decltype

instead of typeof

(which is a compiler extension):

template<>
inline void 
event_handler<decltype(device)::ExampleEvent>(typeof(device) *emitter) 
{
    // event handler implementation...
}

      

Hope it helps. :-)

+1


source


According to the bug report against GCC , this was a known issue and was fixed for GCC 4.7. The GCC upgrade is a long term solution.

The bug report describes a further workaround for using the class template as indirection to bypass the parser in older versions:

class SameType<T> {
  public:
    typedef T R;
}
T<typeof(device)>::ExampleEvent event;

      



This is better than typedef because it generalizes all types of events, but it is still not natural to the user.

This same problem, applied to the new standard operator decltype

, was in fact the subject of a change in the C ++ 11 specification that clarified the rules around parsing types to make this work as expected.

+2


source







All Articles