3

我正在开发一个通过模板使用静态多态性的 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 手册 abouttypeof对该运算符做出以下承诺:

typeof可以在任何可以使用 typedef 名称的地方使用构造。例如,您可以在声明、强制转换或 or 内部使用sizeoftypeof

如果我用typeoftypedef 替换示例中的两个用途,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运算符来消除解析歧义,以便我可以使事件声明单行?

4

2 回答 2

2

根据针对 GCC 的错误报告,这是一个已知问题,已在 GCC 4.7 中修复。升级 GCC 是长期的解决方案。

错误报告描述了在旧版本中使用类模板作为间接绕过解析器的进一步解决方法:

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

这比 typedef 更好,因为它可以泛化到所有事件类型,但对用户来说仍然不自然。

同样的问题,应用于新的标准decltype运算符,实际上是C++11 规范更改的主题,该更改阐明了围绕类型解析的规则,以使其按预期工作。

于 2013-02-03T06:31:40.243 回答
1

我认为一个小的元函数可以解决问题。

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...
}

希望有帮助。:-)

于 2013-02-03T06:20:09.027 回答