19

以下のプログラムで定義されたマップの値を追加しようとしているだけです。

std::map<int, int> floor_plan;

const size_t distance = std::accumulate(std::begin(floor_plan), std::end(floor_plan), 0);

std::cout << "Total: " << distance;

次のエラーが表示されます。

エラー C2893: 関数テンプレート 'unknown-type std::plus::operator ()(_Ty1 &&,_Ty2 &&) const' の特殊化に失敗しました

4

3 に答える 3

34

std::begin(floor_plan)std::map<int, int>::value_typeis を指すイテレータを提供しますstd::pair<const int, int>operator+このペア型と整数が定義されていないため、コードはコンパイルに失敗します。

オプション1

からマップされたすべての値を合計したい場合はfloor_plan、渡された参照解除された反復子の 2 番目の要素を抽出できる独自の二項演算子を提供する必要があります。

std::accumulate(std::begin(floor_plan)
              , std::end(floor_plan)
              , 0
              , [] (int value, const std::map<int, int>::value_type& p)
                   { return value + p.second; }
               );

デモ1

オプション #2

あるいは、Boost.Iteratorライブラリを利用して、ペアの 2 番目の要素をオンザフライで抽出することもできboost::make_transform_iteratorます。

#include <boost/iterator/transform_iterator.hpp>
#include <functional>

auto second = std::mem_fn(&std::map<int, int>::value_type::second);
std::accumulate(boost::make_transform_iterator(std::begin(floor_plan), second)
              , boost::make_transform_iterator(std::end(floor_plan), second)
              , 0);

デモ 2

オプション #3

別のアプローチは、アルゴリズムの独自の実装とともにBoost.Rangeライブラリを使用することです。accumulate

#include <boost/range/numeric.hpp>
#include <boost/range/adaptor/map.hpp>

boost::accumulate(floor_plan | boost::adaptors::map_values, 0);

デモ 3

于 2015-07-11T08:51:19.607 に答える
4

Piotr S. の答えは正しいですが、これが 1 回限りのタスクでない場合は、そのようなタスク用の単純で便利なファンクターを作成することをお勧めします。

struct AddValues
{
  template<class Value, class Pair> 
  Value operator()(Value value, const Pair& pair) const
  {
    return value + pair.second;
  }
};

const size_t distance = std::accumulate(plan.begin(), plan.end(), 0, AddValues());

templatedoperator()のおかげで、このファンクターをコード内の任意の場所に使用できmapます。これは透過的な比較器によく似ていますが、これは透過的な「加算器」です。

于 2015-07-11T10:10:26.103 に答える