4

おそらくブーストでは、コンテナ間で機能する一貫した要素アクセスセマンティクスがありますか?次のようなもの:

element_of(std_pair).get<1>();
element_of(boost_tuple).get<0>();
element_of(pod_array).get<2>();

原則として私は自分で書くことができますが、車輪の再発明はしたくありません。ありがとう

4

3 に答える 3

2

コンテナは本質的に異なるため、コンテナにはさまざまなアクセス方法があります。STL で最も近いのは反復子です。すべての標準コンテナにはイテレータがあるため、イテレータを使用してそれらを反復処理し、同じアルゴリズムを使用できます。ただし、各反復子に含まれるものはコンテナーによって異なります (要素だけが必要ですが、マップにはペアが必要です)。また、ペアをコンテナとして見ている場合、イテレータがないため、残りのペアには適合しません。

ほとんどの場合、反復子を使用すると問題が解決します。ただし、明らかに問題が完全に解決されるわけではなく、STL には解決策がありません。ブーストはあるかもしれませんが、私はそれを知りません。

ただし、要点は、コンテナーは本質的に異なり、大部分は交換可能ではないということです。標準イテレータを使用することで、ほとんどのコンテナを簡単に交換できます。しかし、コードの一部を変更せずに 1 つのコンテナーを別のコンテナーに交換することは、通常は意味がありません。Scott Meyers は、彼の著書「Effective STL」でこれを強調していると思います。

さまざまなコンテナーを交換可能にしようとしている場合は、それを再考し、何をしているかをより詳しく調べることをお勧めします。おそらく、それは最善のアイデアではありません。さて、それはあなたの特定のアプリケーションにとって非常に良い考えかもしれません - 私は確かにそれについて何も知らずに言うことはできません.悪いアイデア。イテレーターを使用すると、多くのアルゴリズムを再利用できますが、特定のコンテナーで使用できるアルゴリズムのタイプは、コンテナーが使用するイテレーターのタイプ (ランダム アクセス、双方向など) によって異なります。

いいえ、イテレータ以外のコンテナ要素にアクセスするための既存のソリューションについては知りませんが、一般的に言えば、それを試みないことをお勧めします。コンテナは真に交換可能ではなく、そうであることを意図していません。

于 2010-01-23T19:36:08.490 に答える
1

私は、C++ の既知のすべてのコンテナー定義で機能する汎用アクセサーを認識していません。ただし、Boost.Rangeはある程度そのまま使用できます。

柔軟性を高めるには、おそらく自分で実装する必要があります。おそらくこれに沿って何かを引っかいてください:

struct container_accessor { ... }
template <typename Container>
container_accessor make_accessor(Container& c) { ... }

template <typename Container>
container_const_accessor make_accessor(Container const& c) { ... }

どこで、必要なすべてのコンテナーに対して container_accessor を特殊化します。

于 2010-01-23T18:34:34.530 に答える
1

私はそのようなことを認識していません。

ほとんどの場合、関心のある型の無料の get 関数を実装するだけで済みます。Boost.Tuple には既にそれがあります。std::pairC++0x に含まれています。そして、残りはあまり複雑であってはなりません。

例えば

#include <iostream>
#include <utility>
#include <vector>
#include <boost/tuple/tuple.hpp>

namespace getter
{
    template <size_t Index, class Container>
    typename Container::reference get(Container& c)
    {
        return c[Index];
    }

    template <size_t Index, class Container>
    typename Container::const_reference get(const Container& c)
    {
        return c[Index];
    }

    template <size_t Index, class T>
    T& get(T *arr)
    {
        return arr[Index];
    }

    namespace detail {
        template <size_t Index, class T, class U>
        struct PairTypeByIndex;

        template <class T, class U>
        struct PairTypeByIndex<0u, T, U>
        {
            typedef T type;
            type& operator()(std::pair<T, U>& p) const { return p.first; }
            const type& operator()(const std::pair<T, U>& p) const { return p.first; }
        };

        template <class T, class U>
        struct PairTypeByIndex<1u, T, U>
        {
            typedef U type;
            type& operator()(std::pair<T, U>& p) const { return p.second; }
            const type& operator()(const std::pair<T, U>& p) const { return p.second; }
        };
    }

    template <size_t Index, class T, class U>
    typename detail::PairTypeByIndex<Index, T, U>::type& get(std::pair<T, U>& p)
    {
        return detail::PairTypeByIndex<Index, T, U>()(p);
    }

    template <size_t Index, class T, class U>
    const typename detail::PairTypeByIndex<Index, T, U>::type& get(const std::pair<T, U>& p)
    {
        return detail::PairTypeByIndex<Index, T, U>()(p);
    }

    using boost::get;
}

int main()
{
    boost::tuple<int, int> tuple(2, 3);
    std::cout << getter::get<0>(tuple) << '\n';
    std::vector<int> vec(10, 1); vec[2] = 100;
    std::cout << getter::get<2>(vec) << '\n';
    const int arr[] = {1, 2, 3, 4, 5};
    std::cout << getter::get<4>(arr) << '\n';
    std::pair<int, float> pair(41, 3.14);
    ++getter::get<0>(pair);
    const std::pair<int, float> pair_ref = pair;
    std::cout << getter::get<0>(pair_ref) << ' ' << getter::get<1>(pair_ref) << '\n';
}
于 2010-01-24T00:05:52.630 に答える