16

編集:興味のある人のためにデザインの変更が完了したら、ここに github リンクを配置します。

バックグラウンド

boost::intrusive, , を独自の実装に置き換えます。これはintrusive_set、64 ビットでコンパイルされた侵入セットがコンテナー ノードに 3 x 8 バイトのポインターを詰め込むためです。私のコンテナーには 2^16 ノードの制限があるため、2x 16 ビットのオフセット序数 (サイズの 6 倍の縮小) を使用して、ノードあたり 4 バイトまで下げることができます。

以下の例baseは、侵入セット コンテナーです。derivedクラスにはstd::vector<container_entry_type<entry_type> >. 明らかに、このレベルの間接化では、ネストされた typedef を派生に含める必要があります。これをベースで参照したいと思います。

ps、コンテナーはデータ記述言語の AST 用です。したがって、含まれる要素は小さなデータ型であり、3 x 8 バイトは非常に重要です。コンテナーはタイトなループでデータセットを検証するために使用されるため、特にそうです。

分離された問題

次のセマンティクスを実現したい:

template<typename TWO>
class base
{
public:
  void foo(typename TWO::dummy & d);
};

template<typename DUMMY>
class derived
  : private base< derived<DUMMY> >
{
public:
  typedef DUMMY dummy;
};

struct tag{};

int main()
{
  derived<tag> foo;
}

しかし、ネストされた typedef にベースからアクセスできません。この問題について、clang は次のように述べています。

main.cc: In instantiation of ‘base<derived<tag> >’:
main.cc:9:7:   instantiated from ‘derived<tag>’
main.cc:20:16:   instantiated from here
main.cc:5:8: error: no type named ‘dummy’ in ‘class derived<tag>’

代わりに、私はしなければなりません:

template<typename type_key>
class traits
{
public:
  typedef type_key dummy;
};

template<typename TWO, typename type_key>
class base
{ 
public:
  void foo(typename traits<type_key>::dummy & d);
};

template<typename DUMMY>
class derived
  : private base< derived<DUMMY>, DUMMY >
{
public:
  typedef DUMMY dummy;
};

struct tag{};

int main()
{
  derived<tag> foo;
}

これが私のユースケースを達成する唯一の方法ですか? 物事がずっと冗長になるだけです。派生は、いくつかのキーストロークを節約するために特性から派生することもできると思います。

もう 1 つの選択肢は、派生を使用せず、現在派生されているものにロジックを直接接続することです。ただし、個別にテストベースを単体テストしたいと思います。

4

3 に答える 3

10

別の可能性(キーストロークを節約できる場合としない場合があります)は、一部の場所で親で派生クラスのネストされた型を使用しないことです。例えば。それ以外の

void foo(typename TWO::dummy & d);

あなたが使うだろう

template <class T>
void foo(typename T& d);

追加のポイントについては、SFINAEを使用Tして、元のバリアントで許可されているタイプに実際に制限することができます。(ネストされたテンプレート内では、TWO::dummy自由に使用できることに注意してください。インスタンス化されるのは、すべてが完了したderivedであるため、うまくいきます。ナイーブバージョンでは、メンバー関数を使用してderivedインスタンス化する時点ではまだ不完全です。baseがない::dummyので失敗します)

于 2011-11-13T19:13:44.150 に答える
5

@jpalecekのアイデアを拡張して、そのテンプレート引数にデフォルトの引数をとらせることができます。ただし、これを取得するにはC++0xを有効にする必要があります

#include <typeinfo>
#include <cstdio>

template<typename TWO>
class base
{
public:
    template <typename X = TWO>   // <-- (requires C++0x to have a default)
    void foo(typename X::dummy& d)
    {
        printf("%s\n", typeid(d).name());
    }
};

template<typename DUMMY>
class derived
  : public base< derived<DUMMY> >
{
public:
  typedef DUMMY dummy;
};

struct tag{};

int main()
{
  derived<tag> foo;
  tag t;
  foo.foo(t);       // <--- call the function like normal.
}

http://ideone.com/AXXdW

于 2011-11-13T19:18:02.427 に答える
1

traitsクラスは必要ありません。type_keyで直接使用できますbase

ただし、型を明示的にに渡すことは避けられませんbase。現時点ではbase、typedef inderivedはコンパイラーによってまだ認識されていません(より正確には、クラスderivedはまだ完全ではありません。基本クラスでさえまだ存在しない場合、どうすればよいでしょうか)。

于 2011-11-13T19:15:09.527 に答える