6

古い質問を保持します。解決策については、以下を参照してください。それはおそらく単純なことですが、それでもです。次の C++11 コード フラグメントがあります。

#include <vector>

template <typename... Ts>
struct typelist
{
};

template <typename T>
struct EventContainer
{
    typedef T Type;
    /// TODO. Ring buffer
    std::vector<T> container;

    void push(const T& t)
    {
        EventContainer<T>::container.push_back(t);
    }

    virtual ~EventContainer()
    {
    }
};


template <template <typename...> class TL>
class EventStorage:
        public EventContainer<Ts>...
{

};

class Event1
{
};

class Event2
{
};

typedef typelist<Event1,Event2> Events12;

int main()
{
    EventStorage<Events12> ev;

    return 0;
}

の各タイプでEventStorage継承テンプレートを作成するにはどうすればよいですか。私は Loki:: ライブラリでそれを行うことができましたが、可変個引数テンプレートで C++11 を使用したいと考えています。ありがとうございました。EventContainertypelist

EventStorage解決策 1:テンプレート テンプレートの問題を修正します。これにより、 の各タイプでテンプレート化されたEventStorageすべてが複数継承されます。EventContainerTs

template <typename...>
class EventStorage
{
};

template <typename... Ts>
class EventStorage < typelist<Ts...> >:
        public EventContainer<Ts>...
{

};

今、私は次のコンパイル時エラーがありますmain():

int main()
{
    EventStorage<Events12> ev;
    Event1 ev1;
    ev.push(ev1);

    return 0;
}

In function ‘int main()’:
error: request for member ‘push’ is ambiguous
error: candidates are: void EventContainer<T>::push(const T&) [with T = Event2]
error: void EventContainer<T>::push(const T&) [with T = Event1]

コンパイラが混乱するのはなぜですか? やはり特定の型で押します。GCC 4.6.1 はこちら。

解決策 2: @Matthieu M. が提案したように、転送メソッド int を提示できますEventStorageが、追加の関数呼び出しが 1 つ必要です。

template <typename T>
void push(const T& t)
{
    EventContainer<T>::push(t);
}

Alexandrescu によると、パラメーターが参照である限り、コンパイラーはこの前方呼び出しを最適化します。これで、質問は正式に終了しました:)

4

2 に答える 2

6

そもそもを紹介する理由はありますtypelistか?

template <typename T> struct Template { void push(T) {} };

template <typename... Args>
class Storage: public Template<Args>...
{
public:
  // forwarding...
  template <typename T>
  void push(T t) {
    Template<T>& me = *this;
    me.push(t);
  }
};

int main() {
  Storage< int, char > storage;
}

これは機能typedefし、全体を実行できStorage<...>ます。

編集:タイプを「組み合わせる」可能性に関するコメントをフォローします。

2つの解決策があります:

template <typename...> struct CombineStorage;

template <typename... A, typename... B>
struct CombineStorage<Storage<A...>, Storage<B...>> {
  typedef Storage<A..., B...> type;
};

または、タイプリストアダプタを提供するだけです。

template <typename... Args>
class Storage<typelist<Args...>>: public Storage<Args...> {};
于 2012-02-15T14:57:26.780 に答える
1

現時点では、typelist のインスタンス化を EventStorage に渡すことすらなく、typelist templateのみを渡します。そのため、現在、拡張するタイプ パックはありません。

ただし、特殊化を使用してタイプリストをアンパックし、それ以外の場合はタイプパックを操作できる必要があります。

template <typename...> class EventStorage;

template <typename Head, typename... Tail> class EventStorage<Head, Tail...>
  : public EventContainer<Head>, EventStorage<Tail...>
{
  using EventContainer<Head>::push;
  using EventStorage<Tail...>::push;
};

// allows you to pass typelists for convenience
template <typename... TL> class EventStorage<typelist<TL...>>
  : public EventStorage<TL...>
{
  using EventStorage<TL...>::push;
};

宣言は、すべてのメソッドを同じオーバーロード セットにusingプルするだけで、私にとってはうまくいくようです。push

別の方法は、明示的に に転送するテンプレート メソッドを追加することです (おそらくトップレベルの型リストの特殊化にのみ) this->EventContainer<T>::push

于 2012-02-15T15:15:20.943 に答える