Сочетание расширения typeof () в GCC с доступом к элементу

Я работаю над библиотекой C ++, которая использует статический полиморфизм через шаблоны. Он спроектирован таким образом, потому что целью является встроенная система с небольшим стеком, и часто это выгодно для inline функции-члены, чтобы сэкономить на использовании стека.

Использование шаблонов для статического полиморфизма означает, что имена типов источников событий (чаще всего драйверов устройств) часто бывают невероятно длинными:

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);

Как видите, мы используем GCC typeof оператор расширения, чтобы не выписывать полное отвратительное имя типа DeviceThatUsesSPI<SoftwareSpiBus<SomeSpecificGpioBus>> несколько раз. Это работало как шарм везде, где мы пробовали его, до сегодняшнего дня я пытался использовать его для доступа к вложенному классу, представляющему событие. В моем текущем примере это специализация шаблона, реализующая привязку обработчика событий во время компиляции:

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

Тем не менее, я также попробовал это в гораздо более минимальном примере объявления переменной:

typeof(device)::ExampleEvent event;

В обоих случаях G ++ не может проанализировать выражение с синтаксической ошибкой. Я предполагаю, что это потому, что в стандартной грамматике C ++ нет ситуации, когда :: следует за чем угодно, кроме идентификатора, и анализатор не может отследить и обработать первую часть как тип, когда он встречает двоеточия.

Тем не мение, руководство GCC о typeof дает следующее обещание об этом операторе:

typeof Конструкция может использоваться везде, где может использоваться имя typedef. Например, вы можете использовать его в объявлении, в приведении или внутри sizeof или же typeof,

Если я заменю два использования typeof в моем примере с typedef G ++ счастлив:

typedef typeof(device) device_type;

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

device_type::ExampleEvent event;

Так что это усиливает мое подозрение, что компилятор в порядке с тем, что я написал семантически, но грамматика не позволяет мне выразить это. Хотя использование перенаправления typedef действительно помогает мне работать с кодом, я бы предпочел найти способ сделать объявления обработчика событий самодостаточными для удобства пользователей этой библиотеки. Есть ли способ написать typeof оператор, чтобы убрать неоднозначность синтаксического анализа, чтобы я мог сделать объявление события однострочным?

3

Решение

Я думаю, что небольшая мета-функция может добиться цели.

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

тогда используйте это как:

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

Или вы можете определить мета-функцию (которая Меньше универсальный) как:

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

тогда используйте это как:

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

Кстати, в C ++ 11 вы можете использовать decltype вместо typeof(который является расширением компилятора):

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

Надеюсь, это поможет. 🙂

1

Другие решения

В соответствии с отчет об ошибках в GCC это была известная проблема, исправленная в GCC 4.7. Модернизация GCC является долгосрочным решением.

В отчете об ошибке описывается еще один обходной путь использования шаблона класса в качестве косвенной меры для обхода синтаксического анализатора в старых версиях:

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

Это лучше, чем typedef, потому что он обобщает все типы событий, но все же неестественно для пользователя.

Эта же проблема, применительно к новому стандарту decltype оператор, был на самом деле предметом изменение спецификации C ++ 11 это прояснило правила разбора типов, чтобы сделать эту работу, как ожидалось.

2

По вопросам рекламы [email protected]