1

私は と をよく知ってboost::anyboost::variantますが、この場合、それらは私のニーズに合いません。

通常、不明なタイプのオブジェクトを含めるには、共通ベースから派生させ、仮想メソッドを介してインスタンスにアクセスします。しかし、共通のベースを使用することが不可能な場合はどうすればよいでしょうか?

この例では、含まれている型を知る必要があることはわかっていますが、ご容赦ください。std::vectorトップレベルクラスもテンプレートであるテンプレートクラスです。私の知る限り、STL ヘッダーを変更せずに非テンプレート ベースを指定することはできません。ここで、単一の型のベクトルを作成したいとしますが、それを含むクラスはその型を気にしませんが、いくつかの「共通」メソッドへのアクセスを必要とsize()pop_back()ます。

を使用するboost::anyと、型が消去され、含まれているオブジェクトを逆参照することがほとんど不可能になります。boost::variantまた、tuple挿入される可能性のある型を事前に知っておく必要があり、それを含むクラス自体がテンプレートになります。

私がこれまでに持っているものは次のようなものです:

struct container
{
    virtual ~container() = 0;
    virtual void pop_back() = 0;
    virtual size_t size() = 0;
    ...
}
template < typename T >
struct contained
{
    std::vector< T > _vec;
    contained ( size_t n, T _what ) : _vec( n, _what ) {}
    virtual void pop_back() { _vec.pop_back(); }
    ...
}
class some_class
{
    container* _cont;
    template < typename T >
    void create ( T _first ) { _cont = new contained< T >(1,_first); }
    ...
}

ここでクライアントが呼び出すことができcreate()、テンプレート パラメータは自動的に決定されます。私が知っている良い例ではありませんが、クライアントからテンプレート パラメーターを隠そうとしています。これを行わないsome_classと、保存されているタイプも追跡する必要があります。

私のメソッドは、特に内部クラスに独自の仮想メソッドがある場合に、パフォーマンスの低下を引き起こす仮想呼び出しに依存しています。

私のニーズにより適した他のタイプのコンテナはありますか?

理想的には、私はこのようなものが欲しい

container = std::vector< T >;
container.pop_back();
container.push_back( T2 ); // compile error if types don't match

仮想メソッドに依存するのではなく、内部的に型を追跡し、単純なキャストを行う場所。違いautoは、一度宣言すると型が変わる可能性があるということです。

編集:

実際には、ラッパーを作成したいと思いますstd::basic_filebufcharこのラッパー クラスは、wchar_tまたはunsigned longBOM に基づいてファイルを開きます。basic_filebufラッパーは、クライアントが選択したものであるテンプレート パラメーターからも派生します。内部的には、Unicode コード ポイントをファイルからクライアントが希望するエンコーディングに変換します。内部を格納するときに問題が発生しbasic_filebufます。これは、テンプレート パラメーターとして任意の型で宣言できるためです。basic_filebufクライアントが独自のインスタンスを渡せるようにしたいので、テンプレートの特殊化を使用したくありません。

C++11 の機能が制限されている VS2010 と互換性がある必要があります。

4

1 に答える 1

0

これをコンパイル時の型チェックと組み合わせることはできません。あなたの「理想的な」例に基づいて:

container c;
if (thingKnownAtRunTime()) {
  c = vector<int>;
} else {
  c = vector<string>;
}
c.push_back("hello world");

ただし、filebuf の場合は、(警告: 未テスト) のようなもので十分にうまくいくかもしれません。

template<typename FILEBUF>
void gensputc(FILEBUF* fb, long long c) {
  FILEBUf::char_type c2 = smart_convert<FILEBUf::char_type>(c);
  fb->sputc(c2);
}

class FileBufWrapper {
public:
  template<typename FILEBUF> FileBufWrapper(FILEBUF* fb) {
    fb_ = fb;
    sputc_ = gensputc<FILEBUF>;
  }
  void sputc(long long c) {
    sputc_(fb_,c);
  }
private:
  typedef void(*sputc_t)(void*, long long);
  sputc_t sputc_;
  void* fb_;
};

値を char 型に変換できない場合、smart_convert 関数は実行時例外をスローします。また、これは、呼び出す予定のすべての関数に対して行う必要があります。

C++11 の std::function と std::bind にアクセスできる場合、特に何も変換する必要がない場合に、これを少しすっきりさせることができます。

于 2013-08-13T20:13:52.003 に答える