2013-11-27 31 views
8

私は、コンテナの要素を合計する関数を書くことを試みます。このコンテナはVector、List、Queueなどです。そのため、テンプレートを試したのです。イテレータを関数パラメータとして渡す

は、残念ながら、私はこのエラーを取得する:

'C' is not a template

出典:

#include <iostream> 
#include <vector> 

using namespace std; 

template<class C, typename T> 
T sum(C<T>::iterator begin, C<T>::iterator end) { 
    T s = null; 

    for (C<T>::iterator it = begin; it != end; it++) { 
     s += *it; 
    } 

    return s; 
} 

int main() 
{ 
    vector<int> v = {5, 9, 0, 11}; 

    cout << sum(v.begin(), v.end()) << endl; 

    return 0; 
} 

私が間違って何をしますか?どのように修正する必要がありますか?

答えて

7

特定のエラー、あなたをテンプレートテンプレートの引数が必要なためです:

template<template <typename> class C, typename T> 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
T sum(C<T>::iterator begin, C<T>::iterator end) 

しかし、標準コンテナは通常、ただ1つのテンプレート引数よりも持っている:

template < class T, class Alloc = allocator<T> > class vector 

をし、正しく、このような関数を記述するためにビット非自明です。あなたは可変長テンプレート引数を使用することができ、または標準ライブラリがないようにあなたが行うことができ、そして唯一のあなたが本当に必要なだけを特化:

// <algorithm> 
namespace std { 
    template <class RandomAccessIterator> 
    void sort (RandomAccessIterator first, RandomAccessIterator last); 
} 

あなたのケースでは(あなたの必要性は、標準的なアルゴリズムライブラリによってカバーされていないことをふりすでに):

template <typename Iterator> 
auto sum(Iterator begin, Iterator end) 
-> decltype(*begin+*begin) // the type of summing two of them 
{ 
    if (begin == end) throw std::logic_error("...."); 
    auto s = *begin; 
    ++begin; 
    for (; begin != end; ++begin) { 
     s += *begin; 
    } 
    return s; 
} 

あなたの元のコードからいくつかのより多くの違いがあります。

  • 新しいコードは(it)追加のイテレータを導入しないnullまたはデフォルトコンストラクタ定義された(T s = null;
  • を負いません
  • は、プリインクリメント
  • を使用しています==最後
を開始するときに例外がスローされます

あなたがinitパラメータを追加した場合、あなたはそれを作ることができ、ほぼnoexcept

template <typename Iterator, typename T> 
T sum(Iterator begin, Iterator end, T init) 
{ 
    for (; begin!=end; ++begin) 
     init += *begin; 
    return init; 
} 

しかし、ほとんどの場合、init += *beginがまだ投げることができます。

このような署名をお持ちでしたら、std::accumulateの署名を再現したことがあります。

14

あなたはイテレータ型の面で全体のことを表現し、VALUE_TYPE取得するiterator_traitsを使用することができます。

#include <iterator> 

template<typename Iterator> 
typename std::iterator_traits<Iterator>::value_type 
sum(Iterator begin, Iterator end) 
{ 
    using value_type = typename std::iterator_traits<Iterator>::value_type; 
    value_type s = value_type(); 
    for (Iterator it = begin; it != end; it++) { 
    s += *it; 
    } 
    return s; 
} 

現実の生活では、std::accumulate使用:

int sum = std::accumulate(v.begin(), v.end(), 0); 
+2

+1。しかし確かに 'std :: iterator_traits :: value_type s;'? –

+0

@ Moo-Juiceありがとう、それを修正しました。私の編集が悪い – juanchopanza

関連する問題