6

一連のデータポイントを (名前, 値) の形式で保存する必要があります。値はさまざまな型を取ることができます。

各データポイントにクラス テンプレートを使用しようとしています。次に、表示されるデータ ポイントごとに、新しいオブジェクトを作成し、それをベクトルにプッシュします。新しい型ごとに、最初にテンプレートから新しいクラスを作成する必要があります。しかし、ベクトルはすべてのエントリに対して同じタイプを想定しているため、任意のベクトルで作成されたオブジェクトを格納することはできません。保存する必要がある型は、継承階層に収まりません。それらは無関係です。また、将来さらに多くのタイプが作成される可能性があるため、新しいタイプごとにストレージ サービスを変更したくありません。これらのエントリを格納する異種コンテナを作成する方法はありますか? ありがとうございました!

4

4 に答える 4

10

C++17以降。

std::any任意のタイプを保持できますが、それを取得するために保存されたタイプを知っている必要があります。

ただし、既知のタイプのセットがある場合は、次のことをお勧めしますstd::variant

using variant_type = std::variant<Foo, Bar, Joe>;

int func(variant_type const& v) // not template
{
    auto const visitor = [](auto const& t)
    {
        if constexpr (std::is_same_v<Foo const&, decltype(t)>)
        {
            return t.fooish();
        }
        else
        {
            return t.barjoeish();
        }
    };

    return std::visit(visitor, v);
}

訪問者をすばやく定義するための便利なトリック:

template <typename... Ts> struct overload : Ts...
{
    overload(Ts... aFns) : Ts(aFns)... {}
    using Ts::operator()...;
};
template <typename... Ts> overload(Ts...) -> overload<Ts...>;

//  Used as
auto const visitor = overload(
    [](Foo const& foo) { return foo.fooish(); },
    [](auto const& other) { return other.joebarish(); }
);

return std::visit(visitor, variant);

Pre-C++17。

boost::anyすでに推奨されていますが、それは何のためでもあるので、あなたはそれから多くを期待することはできません。

さまざまなタイプを事前に知っている場合は、を使用することをお勧めしますboost::variant

typedef boost::variant<Foo, Bar, Joe> variant_type;

struct Print: boost::static_visitor<>
{
  void operator()(Foo const& f) const { f.print(std::cout); }

  template <class T>
  void operator()(T const& t) const { std::cout << t << '\n'; }
};

void func(variant_type const& v) // not template
{
  boost::apply_visitor(Print(), v); // compile-time checking
                                    // that all types are handled
}
于 2010-07-09T16:19:41.303 に答える
7

ブースト ライブラリには、おそらく探しているものが含まれています (boost::any)。ブーストを使用できない場合は、ラップされたポインターアプローチを使用して独自にロールバックできます...

于 2010-07-09T11:21:09.277 に答える
4

このようなコンテナーの問題は、コンテナー内の何かにアクセスしたい場合、その型を特定してから実際の型に何らかの方法でキャストする必要があることです。これは見栄えが悪く、非効率的で、エラーが発生しやすいため、C++ での第 1 の選択肢は継承を使用することです。ただし、継承を使用しない十分な理由がない限り、C++ のキャリアで実際に遭遇したことはありません。

于 2010-07-09T11:25:58.393 に答える
0

私は、Pair(type, void*) を持っていて、ペアで記述されている型に応じて void* をキャストする独自の pop 関数を作成し、これらを目に入るコンテナーに押し込むことができると考えていました。

于 2010-07-09T11:24:46.210 に答える