コンテナの要素を合計する関数を書こうとしています。このコンテナには、Vector、List、Queueなどがあります。そのため、テンプレートを試しました。
残念ながら、このエラーが発生します。
「C」はテンプレートではありません
ソース:
#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;
}
何が間違っていますか?どうすれば修正できますか?
発生する特定のエラーは、テンプレートテンプレート引数が必要になるためです。
template<template <typename> class C, typename T>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
T sum( C<T>::iterator begin, C<T>::iterator end )
ただし、標準コンテナには通常、複数のテンプレート引数があります。
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;
}
元のコードとはさらにいくつかの違いがあります。
T s = null;
)it
)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
の署名を複製したことになります。
全体をイテレータ型で表現し、iterator_traits
を使用してvalue_typeを取得できます。
#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);