58

すべてのデータ型オブジェクトメンバー関数で呼び出しを実行したいマップがあります。私はまだどのシーケンスでもこれを行う方法を知っていますが、連想コンテナでそれを行うことは可能ですか?

私が見つけた最も近い答えはこれでした:std::for_eachのstd::map要素にアクセスするためのBoost.Bind。しかし、私のプロジェクトではブーストを使用できないので、boost :: bindに欠けているSTLの代替手段はありますか?

不可能な場合は、データオブジェクトへのポインターの一時シーケンスを作成してから、次のようにfor_eachを呼び出すことを検討しました。

class MyClass
{
public:
 void Method() const;
}

std::map<int, MyClass> Map;
//...

std::vector<MyClass*> Vector;
std::transform(Map.begin(), Map.end(), std::back_inserter(Vector), std::mem_fun_ref(&std::map<int, MyClass>::value_type::second));
std::for_each(Vector.begin(), Vector.end(), std::mem_fun(&MyClass::Method));

それはあまりにも曖昧に見え、私はそれが本当に好きではありません。助言がありますか?

4

11 に答える 11

129

C ++ 11では、次のことができます。

for (const auto& kv : myMap) {
    std::cout << kv.first << " has value " << kv.second << std::endl;
}

C ++ 17では、次のことができます。

for (const auto& [key, value] : myMap) {
    std::cout << key << " has value " << value << std::endl;
}

構造化バインディングを使用します。

アップデート:

マップを変更したくない場合は、constautoの方が安全です。

于 2014-05-27T13:53:46.483 に答える
64

オブジェクトを反復処理できstd::mapます。std::pair<const T,S>各イテレータはwhereTを指し、はでS指定したのと同じタイプですmap

これは次のようになります。

for (std::map<int, MyClass>::iterator it = Map.begin(); it != Map.end(); ++it)
{
  it->second.Method();
}

それでも使用したい場合は、代わりに引数としてstd::for_eachをとる関数を渡します。std::pair<const int, MyClass>&

例:

void CallMyMethod(std::pair<const int, MyClass>& pair) // could be a class static method as well
{
  pair.second.Method();
}

そしてそれをに渡しますstd::for_each

std::for_each(Map.begin(), Map.end(), CallMyMethod);
于 2010-05-17T15:24:03.467 に答える
15

C++14は一般的なラムダをもたらします。std :: for_eachを非常に簡単に使用できることを意味します:

std::map<int, int> myMap{{1, 2}, {3, 4}, {5, 6}, {7, 8}};

std::for_each(myMap.begin(), myMap.end(), [](const auto &myMapPair) {
    std::cout << "first " << myMapPair.first << " second "
              << myMapPair.second << std::endl;
});

std :: for_eachは、forループに基づく単純な範囲よりも適している場合があると思います。たとえば、マップのサブセットのみをループする場合です。

于 2015-11-13T20:02:24.873 に答える
8

プレーンなC++はどうですか?(@Noah Robertsのメモに従って修正された例)

for(std::map<int, MyClass>::iterator itr = Map.begin(), itr_end = Map.end(); itr != itr_end; ++itr) {
  itr->second.Method();
}
于 2010-05-17T15:23:36.527 に答える
3

Boostがないのは残念ですが、STL実装に拡張機能がある場合は、mem_fun_refとselect2ndを作成して、for_eachでの使用に適した単一のファンクターを作成できます。コードは次のようになります。

#include <algorithm>
#include <map>
#include <ext/functional>   // GNU-specific extension for functor classes missing from standard STL

using namespace __gnu_cxx;  // for compose1 and select2nd

class MyClass
{
public:
    void Method() const;
};

std::map<int, MyClass> Map;

int main(void)
{
    std::for_each(Map.begin(), Map.end(), compose1(std::mem_fun_ref(&MyClass::Method), select2nd<std::map<int, MyClass>::value_type>()));
}

compose1(またはunary_composeテンプレート)とselect2ndにアクセスできない場合は、かなり簡単に記述できることに注意してください。

于 2010-05-17T15:47:31.693 に答える
2

グーグルからのこの質問に出くわした仲間のプログラマーにとって、ブーストを使用する良い方法があります。

ここで説明:std::mapでboost::foreachを使用することは可能ですか?

あなたの便宜のための実際の例:

// typedef in include, given here for info : 
typedef std::map<std::string, std::string> Wt::WEnvironment::CookieMap

Wt::WEnvironment::CookieMap cookie_map = environment.cookies();

BOOST_FOREACH( const Wt::WEnvironment::CookieMap::value_type &cookie, cookie_map )
{
    std::cout << "cookie : " << cookie.first << " = " << cookie.second << endl;
}

楽しい。

于 2011-12-25T22:12:31.710 に答える
0

私が覚えていることから、C ++マップはmap.begin()を使用してキーのイテレーターを返すことができ、そのイテレーターを使用して、map.end()に到達するまですべてのキーをループし、対応する値を取得できます: C ++ map

于 2010-05-17T15:22:41.450 に答える
0

それはあなたのために働きますか?

class MyClass;
typedef std::pair<int,MyClass> MyPair;
class MyClass
{
  private:
  void foo() const{};
public:
static void Method(MyPair const& p) 
{
    //......
        p.second.foo();
};
}; 
// ...
std::map<int, MyClass> Map;
//.....
std::for_each(Map.begin(), Map.end(), (&MyClass::Method));
于 2010-05-17T15:35:04.407 に答える
0

ほんの一例:

template <class key, class value>
class insertIntoVec
{
public:
    insertIntoVec(std::vector<value>& vec_in):m_vec(vec_in)
    {}

    void operator () (const std::pair<key, value>& rhs)  
    {   
        m_vec.push_back(rhs.second);
    }

private:
    std::vector<value>& m_vec;
};

int main()
{
std::map<int, std::string> aMap;
aMap[1] = "test1";
aMap[2] = "test2";
aMap[3] = "test3";
aMap[4] = "test4";

std::vector<std::string> aVec;

aVec.reserve(aMap.size());
std::for_each(aMap.begin(), aMap.end(),
          insertIntoVec<int, std::string>(aVec) 
    );

}

于 2010-05-17T15:36:21.520 に答える
0

私はあなたが探していることをするためにしばらく前にこれを書きました。

namespace STLHelpers
{
    //
    // iterator helper type for iterating through the *values* of key/value collections
    //

    /////////////////////////////////////////////
    template<typename _traits>
    struct _value_iterator
    {
        explicit _value_iterator(typename _traits::iterator_type _it)
            : it(_it)
        {
        }

        _value_iterator(const _value_iterator &_other)
            : it(_other.it)
        {
        }

        friend bool operator==(const _value_iterator &lhs, const _value_iterator &rhs)
        {
            return lhs.it == rhs.it;
        }

        friend bool operator!=(const _value_iterator &lhs, const _value_iterator &rhs)
        {
            return !(lhs == rhs);
        }

        _value_iterator &operator++()
        {
            ++it;
            return *this;
        }

        _value_iterator operator++(int)
        {
            _value_iterator t(*this);
            ++*this;
            return t;
        }

        typename _traits::value_type &operator->()
        {
            return **this;
        }

        typename _traits::value_type &operator*()
        {
            return it->second;
        }

        typename _traits::iterator_type it;
    };

    template<typename _tyMap>
    struct _map_iterator_traits
    {
        typedef typename _tyMap::iterator iterator_type;
        typedef typename _tyMap::mapped_type value_type;
    };

    template<typename _tyMap>
    struct _const_map_iterator_traits
    {
        typedef typename _tyMap::const_iterator iterator_type;
        typedef const typename _tyMap::mapped_type value_type;
    };
}
于 2010-05-17T16:40:40.400 に答える
0

これは、マップにfor_eachを使用する方法の例です。

std::map<int, int> map;

map.insert(std::pair<int, int>(1, 2));
map.insert(std::pair<int, int>(2, 4));
map.insert(std::pair<int, int>(3, 6));

auto f = [](std::pair<int,int> it) {std::cout << it.first + it.second << std::endl; };
std::for_each(map.begin(), map.end(), f);
于 2019-01-04T16:40:33.637 に答える