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

ご覧のとおり、GCCtypeof拡張演算子を使用して、不快な型名全体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

私の例の2つの使用法を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イベント宣言をワンライナーにできるように、解析のあいまいさを取り除く演算子を作成する方法はありますか?

4

2 に答える 2

2

GCCに対するバグレポートによると、これは既知の問題であり、GCC4.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 に答える