我正在开发一个通过模板使用静态多态的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 ++语法中没有::
跟随除标识符之外的任何内容的情况,并且解析器在遇到冒号时无法回溯并将第一部分视为类型。
但是,the GCC manual about typeof
对此运算符做出以下承诺:
可以在任何可以使用typedef名称的地方使用
typeof
构造。例如,您可以在声明,演员表或sizeof
或typeof
内部使用它。
如果我使用typedef替换我的示例中typeof
的两种用法,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
运算符来消除解析歧义,以便我可以将事件声明设为一行?
答案 0 :(得分:2)
根据a bug report against GCC,这是一个已知问题,并已修订为GCC 4.7。升级GCC是一项长期解决方案。
错误报告描述了使用类模板作为间接来绕过旧版本解析器的进一步解决方法:
class SameType<T> {
public:
typedef T R;
}
T<typeof(device)>::ExampleEvent event;
这比typedef更好,因为它可以推广到所有事件类型,但对用户来说仍然不自然。
同样的问题,应用于新的标准decltype
运算符,实际上是a C++11 specification change的主题,澄清了类型解析的规则,使其按预期工作。
答案 1 :(得分: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...
}
或者您可以将元功能( less generic)定义为:
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...
}
希望有所帮助。 : - )