26

次のようなデータのさまざまな要件に基づいて、どのSTLコンテナが適しているかを分類するこの素晴らしいグラフィックを見ました。

-固定サイズと可変サイズ

-同じタイムと異なるタイプのデータ

-ソートされたデータとソートされていないデータ

-シーケンシャルvsランダムアクセス

http://plasmahh.projectiwear.org/cce_clean.svg

その画像で、C++STLにはコンテナがないことに気づきました。

  1. 可変サイズ
  2. 異種(さまざまなタイプのデータ)。

C ++にはこれのための何かがありませんか?

PS-コンテナのさまざまなプロパティから多くの順列が作成される可能性があり、他の多くの順列もSTLで提供されない可能性があります。

4

7 に答える 7

20

一般的に、C ++コンテナは、テンプレートを使用して単一タイプのオブジェクトを保持するように設計されています。すべて1つの型から派生したさまざまな型が必要な場合は、ポインターのコンテナーを格納できます(void *のコンテナーを任意のものに格納することもできます...)。例:std :: vector<MyBaseType*>。

完全に無関係なタイプが必要な場合は、boost::anyなどの他のタイプを安全に参照できるオブジェクトを保存できます。

http://www.boost.org/doc/libs/1_47_0/doc/html/any.html

ブーストサイトからのいくつかの例:

#include <list>
#include <boost/any.hpp>

using boost::any_cast;
typedef std::list<boost::any> many;

void append_int(many & values, int value)
{
    boost::any to_append = value;
    values.push_back(to_append);
}

void append_string(many & values, const std::string & value)
{
    values.push_back(value);
}

bool is_int(const boost::any & operand)
{
    return operand.type() == typeid(int);
}
bool is_char_ptr(const boost::any & operand)
{
    try
    {
        any_cast<const char *>(operand);
        return true;
    }
    catch(const boost::bad_any_cast &)
    {
        return false;
    }
}

boost :: Variantも同様ですが、コンテナで任意のタイプを許可するのではなく、許可されるすべてのタイプを指定します。

http://www.boost.org/doc/libs/1_47_0/doc/html/variant.html

std::vector< boost::variant<unsigned, std::string> > vec;
vec.push_back( 44);
vec.push_back( "str" );
vec.push_back( SomthingElse(55, 65) ); //not allowed
于 2011-10-18T09:23:05.107 に答える
10

標準ライブラリの基本原則は、「コンテナ」が同種であるということです。std::pairC ++標準では、コンテナのようなものやコンテナとは見なされませんstd::tuple。(グラフはコンテナーと見なされるため、誤解を招くと思います。)異種コンテナーが必要な場合は、のコンテナーboost::variant、またはそれらの線に沿った何かを使用する必要があります。

于 2011-10-18T09:22:29.103 に答える
5

Boostにまだ受け入れられていないライブラリ。しかし、含めるために提案されたものはこれを対象としています:

http://rawgit.com/joaquintides/poly_collection/website/doc/html/index.html

これはany_collectionという名前の素晴らしいクラスを提供し、boost :: type_erasure :: any:http://rawgit.com/joaquintides/poly_collection/website/doc/html/poly_collection/tutorial.html#poly_collectionを介して異種コンテナーを持つことができます 。 tutorial.basics.boost_any_collection

それ以外の場合、C ++ 17ではこれを実装する簡単な方法があります: https ://gieseanw.wordpress.com/2017/05/03/a-true-heterogeneous-container-in-c/

前述の記事の例を引用すると:

namespace andyg{
struct heterogeneous_container{
private:
    template<class T>
    static std::unordered_map<const heterogeneous_container*, std::vector<T>> items;
public:
    template <class T>
    void push_back(const T& _t)
    {
        items<T>[this].push_back(_t);
    }
};

// storage for our static members
template<class T>
std::unordered_map<const heterogeneous_container*, std::vector<T>> heterogeneous_container::items;
} // andyg namespace

その後、簡単に使用できます:

andyg::heterogeneous_container c;
c.push_back(1);
c.push_back(2.f);
c.push_back('c');
struct LocalStruct{};
c.push_back(LocalStruct{});

著者はそれがおもちゃの実装であると述べていますが、これはそれを実装するための本当に賢い方法であり、poly_collectionやバリアントのベクトルよりも単純な利点があると思います。

于 2017-05-12T13:08:20.270 に答える
4

std::pairそしてstd::tuple、ほとんどC ++コンテナではありません....したがって、STLには異種コンテナはありません。これは、それらを組み込む必要がないためです。

このようなコンテナを作成するには、いくつかのアプローチがあります。私がお勧めするアプローチは次のとおりです。

  • ポリモーフィズムを使用する
  • バリアント型を使用する

ポリモーフィズムについては、 BoostPointerContainerライブラリを確認できます。

boost::ptr_vector<Base> vec;
vec.push_back(new Derived);
vec.push_back(new Derived2);

これはSTLコンテナーを模倣しますが、ポリモーフィズムに向けた機能を提供します。

  • として要素にアクセスBase&
  • 自動メモリ処理
  • 特定のコピー動作(new_cloneメソッドを使用)
  • シンタックスシュガー:与えられたboost::ptr_vector<Base>::iterator it;*itBase&

タイプが無関係の場合、他の可能性はBoostVariantを使用することです。基本的に、バリアントは次のようになります。

enum { Type1, Type2, ... } _type;
union {
  SomeType1 _1;
  SomeType2 _2;
  ...
} _u;

もちろん、ブーストであるため、現在アクティブなユニオンのメンバーにのみアクセスできるようにするための特定の保証が提供され、コンストラクタ/デストラクタが従来のユニオンで使用できないクラスの制限が解除されます。

また、タイプのスイッチに相当するのような機能も提供しstatic_visitor、可能な状態の1つにアクセスしないと、コンパイルエラーが発生します。

于 2011-10-18T09:44:32.603 に答える
2

固定サイズの異種コンテナー(std::tupleコンパイル時に型を認識している必要があるなど。可変サイズの異種コンテナーを作成する場合は、を作成するだけstd::vector<std::tuple<T1,T2,...,TN>>です。

コンパイル時に型が不明な異種コンテナーが必要な場合(可変サイズか固定サイズかに関係なく)、コンパイル時に既知の基本型へのポインター(またはスマートポインター)を格納するか、代わりに何かを検討する必要があります。のコンテナのようにboost::any。STLは、実行時に決定される異種要素を使用して、固定サイズまたは可変サイズのコンテナを直接提供しません。

于 2011-10-18T09:25:27.123 に答える
1

保存する要素がまたはの場合、boost::any異種boost::variantデータを間接的に保存できます。

于 2011-10-18T09:21:08.847 に答える
1

このライブラリを紹介します。真の異種コンテナとして実装されてい ますhttps://github.com/hosseinmoein/DataFrame ポリモーフィズムを使用しないため、ポインターを格納します。std :: vectorと同じように、継続的なメモリストレージを使用します。

このようなコードを書くことができます

typedef StdDataFrame<unsigned long> MyDataFrame;

MyDataFrame                df;
std::vector<int>           intvec = { 1, 2, 3, 4, 5 };
std::vector<double>        dblvec = { 1.2345, 2.2345, 3.2345, 4.2345, 5.2345 };
std::vector<double>        dblvec2 = { 0.998, 0.3456, 0.056, 0.15678, 0.00345,
                                       0.923, 0.06743, 0.1 };
std::vector<std::string>   strvec = { "Insight", "John Dow", "Alakazam",
                                      "Persian Prince", "Bugs Bunny" };
std::vector<unsigned long> ulgvec = { 1UL, 2UL, 3UL, 4UL, 5UL, 8UL, 7UL, 6UL }
std::vector<unsigned long> xulgvec = ulgvec;

// This is only one way of loading data into a DataFrame instance. There are
// many different ways of doing it. Please see the documentation,
// or dataframe_tester.cc
int rc = df.load_data(std::move(ulgvec),  // Index column
                      std::make_pair("int_col", intvec),
                      std::make_pair("dbl_col", dblvec),
                      std::make_pair("dbl_col_2", dblvec2),
                      std::make_pair("str_col", strvec),
                      std::make_pair("ul_col", xulgvec));
于 2020-01-02T16:19:47.770 に答える