0

ベクトル/リストまたはマップのいずれかで動作する Sum 関数のオーバーロードにまだ取り組んでいます。sum 関数のベクトル/リスト バージョンは正常に動作し、マップ バージョンのコードはかなりまともだと思いますが、テストすると、関数のリスト/ベクトル バージョンを呼び出そうとしているとコンパイラが認識しているようです。 、いくつかのコンパイラ エラーをスローします。関連するコードは次のとおりです。

template <typename T>
const double Sum(typename T start_iter, typename T end_iter)
{// code...
}

template <typename T>
const double Sum(map<typename T, double> start_iter, map<typename T, double> end_iter)
{// different code...
}

int main()
{

map<string, double> test_map; // construct empty map

test_map["Line1"] = 10; // add some data
test_map["Line2"] = 15; 

Sum(test_map.begin(),test_map.end()) // this tries to call the list/vector version of sum
}

これらの関数をどのように混同していますか? ありがとう!

4

2 に答える 2

2

コメントで議論されているもののわずかな代替:

template <typename Vt>
struct getter
{
  Vt operator()(const Vt& v)
  {
    return v;
  }
};

template <typename F, typename G>
struct getter<std::pair<F, G> >
{
  G operator()(const std::pair<F, G>& v)
  {
    return v.second;
  }
};


template <typename Iterator>
int sum(Iterator it, Iterator end)
{
  int r = 0;
  for(; it != end; ++it)
    r += getter<typename Iterator::value_type>()(*it);
  return r;
}

これで、sum関数は何を繰り返しているかを気にせず、値を取得するために適切なものに頼るだけgetterです...

例えば:

  std::map<int, int> f;
  f[1] = 3;
  f[2] = 6;
  f[3] = 12;
  f[4] = 24;

  std::vector<int> g;
  g.push_back(4);
  g.push_back(8);
  g.push_back(16);
  g.push_back(32);

  std::cout << sum(f.begin(), f.end()) << std::endl;
  std::cout << sum(g.begin(), g.end()) << std::endl;
于 2012-10-01T09:15:27.020 に答える
0

前の説明で説明したように、コンパイラは のパラメーターとして指定された反復子のコンテナーの型を推測できませんSum

std::map<X,Y>::iterator::value_typeただし、値のペアであるという事実を使用することは可能ですstd::pair<XX, YY>。もちろん、これは の目的の特殊化Sumstd::mapイテレータに制限するのではなく、要素のペアを返す任意のコンテナ イテレータ (例: . std::vector< std::pair<std::string, double> >)に制限します。

これが気にならない場合、または sthg likestd::vector< std::pair<std::string, double> >が同じ特殊化を使用する必要がある場合、次のコードはあなたの場合に望ましい結果をもたらすようです:

#include <map>
#include <string>
#include <iostream>
#include <cassert>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>


// a small structure to 
template <class U>
struct is_a_key_pair_it
{
  typedef boost::false_type type;
};

template <class A, class B>
struct is_a_key_pair_it< std::pair<A, B> >
{
  typedef boost::true_type type;
};

// using boost::disable_if to avoid the following code to be instanciated 
// for iterators returning a std::pair
template <typename T>
const double Sum(T start_iter, T end_iter, 
  typename boost::disable_if<
    typename is_a_key_pair_it<
      typename boost::remove_reference<typename T::value_type>::type 
    >::type >::type * dummy = 0)
{
  // code...
  std::cout << "non specialized" << std::endl;
  return 0;
}

// using boost::enable_if to limit the following specializing of Sum
// to iterators returning a std::pair
template <typename T>
const double Sum(T start_iter, T end_iter, 
  typename boost::enable_if<
    typename is_a_key_pair_it<
      typename boost::remove_reference<typename T::value_type>::type 
    >::type >::type * dummy = 0)
{
  // different code...
  std::cout << "specialized" << std::endl;
  return 1;
}




int main()
{
  typedef std::map<std::string, double> map_t;

  // check
  assert(is_a_key_pair_it<map_t::iterator::value_type>::type::value);
  // works also for const_iterators
  assert(is_a_key_pair_it<map_t::const_iterator::value_type>::type::value);

  map_t test_map;
  test_map["Line1"] = 10; // add some data
  test_map["Line2"] = 15; 

  double ret = Sum(test_map.begin(),test_map.end()); 
}
于 2012-10-02T08:34:48.257 に答える