宜しくお願いします。
このプログラムのコンストラクタからexcel のSUM 計算のようなことを行いたいのですが
error C2440: '=' : 'MovingAve<T,Iterator>' から 'int' に変換できません。
エラーが出ます、何処が不味いのでしょうか?
また、for 文を、transform を用いて書き直したいのですが、
transform( first, last, back_inserter(m_vec), Sum<int>( sum, first, last ) );
としますと、
error C2064: 1 引数を取り込む関数には評価されません。
調べると、関数ポインタとして評価されない式を使って、関数を呼び出そうとしました。
関数のポインタとして評価されない式を使って、関数の呼び出しが行われました。
このエラーは通常、関数でないものを呼び出そうとしたときに発生します。 とのことですが
Sum<int>( sum, first, last ) 恐らくこの部分の定義、または、呼び出し方法が間違っ
ていると想像しますがわかりません
合わせてご教示願えないでしょうか。
(コンパイラVS2005)
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
template <class T, class Iterator>
class MovingAve
{
Iterator first_;
Iterator last_;
public:
MovingAve(Iterator first = MovingAve(), Iterator last = MovingAve()) :
first_(first), last_(last) {}
T operator()(Iterator first, Iterator last);
T Sum(Iterator& first, Iterator& last);
};
template <class T, class Iterator>
T MovingAve<T, Iterator>::operator()(Iterator first, Iterator last)
{
T sum = 0;
while ( first_ != last_ ) {
sum+=*first_;
++first_;
}
return sum;
}
template <class T, class Iterator>
T Sum(Iterator& first, Iterator& last)
{
T sum = 0;
while ( first != last ) {
sum+=*first;
++first;
}
return sum;
}
int main()
{
int sum;
vector<int> vec, m_vec;
vector<int>::iterator first, last;
for( int i = 0; i<10 ;++i ) { vec.push_back(i+1); }
int period = 3;
int array_size = vec.size();
array_size-=period;
//first = vec.begin();
//last = vec.begin() + period;
//sum = 0;
//transform( first, last, back_inserter(m_vec), Sum<int>(first, last) );//エラー
for(int i=0; i < array_size; ++i) {
sum = 0;
if (i < period) {
sum = 0;
} else {
first = vec.begin() + i; last = vec.begin() + i + period;
sum = Sum<int>( first, last );
//sum = MovingAve<int, vector<int>::iterator >( first, last );//エラー
}
m_vec.push_back(sum);
}
copy(m_vec.begin(), m_vec.end(), ostream_iterator<int>(cout, \n));
return 0;
}
よくわかんないけど、要はズラしながら部分和を取りたいのね。
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int main() {
std::vector<int> vec, m_vec;
for( int i = 0; i<10 ;++i ) { vec.push_back(i+1); }
int period = 3;
int array_size = vec.size() - period;
std::vector<int>::iterator first = vec.begin();
std::vector<int>::iterator last = vec.begin();
std::advance(last,period);
for ( int i = 0; i < array_size; ++i ) {
m_vec.push_back(std::accumulate(first, last, 0));
++first; ++last;
}
std::copy(m_vec.begin(), m_vec.end(), std::ostream_iterator<int>
(std::cout, \n));
return 0;
}
επιστημη さんありがとございます、
>よくわかんないけど、要はズラしながら部分和を取りたいのね。
若干異なりますが、その通りです(部分集合の要素数がperiod より少ない場合は0 で埋
めたいですが、それは大きな問題ではありません)
std::accumulate ですか、知りませんでした、コードが短く解りやすくなりました。
ところで、私の書いたごみのようなコードですが、
MovingAve(Iterator first = MovingAve(), Iterator last = MovingAve()) :
first_(first), last_(last) {}
↓変更
MovingAve(Iterator first, Iterator last) : first_(first), last_(last) {}
transform( first, last, back_inserter(m_vec), Sum<int>(first, last) );//エラー
↓変更
transform( first, last, back_inserter(m_vec), MovingAve<int,
vector<int>::iterator >() );
このように、コンストラクタとtranform を変更するのですが
error C2512: 'MovingAve<T,Iterator>::MovingAve' : クラス、構造体、共用体に既定の
コンストラクタがありません。
となってしまいます。
私の考えでは
MovingAve<int, vector<int>::iterator >()
この() の部分に
first とlast が代入されるという認識なのですが、間違ってますでしょうか?
...ごめん、MovingAveとやらに求められる挙動がわかんない。
コンストラクト時に何を与え、operator()で何を返したいのでしょうか?
すみません説明不足で、このようなことがしたいのですが、可能でしょうか?
transform( first, last, back_inserter(m_vec), ここでMovingAve の①→①´戻り値として
部分和を得たい。 );
①T operator()(Iterator first, Iterator last);
↓
①´
template <class T, class Iterator>
T MovingAve<T, Iterator>::operator()(Iterator first, Iterator last)
{
T sum = 0;
while ( first_ != last_ ) {
sum+=*first_;
++first_;
}
return sum;
}
補足します
/** @brief operator() を使用し部分和を求める
* @param[in] Iterator first 求値したい範囲の先頭を指し示す
* @param[in] Iterator last 求値したい範囲の終端を指し示す
* @return 部分和を返却
*/
template <class T, class Iterator>
T MovingAve<T, Iterator>::operator()(Iterator first, Iterator last)
{
T sum = 0;
while ( first_ != last_ ) {
sum+=*first_;
++first_;
}
return sum;
}
すみません修正です変数名のアンダーバーは要りませんでしたというか、在ると
セマンティクス的に間違ってます。
/** @brief operator() を使用し部分和を求める
* @param[in] Iterator first 求値したい部分範囲の先頭を指し示す
* @param[in] Iterator last 求値したい部分範囲の終端を指し示す
* @return 部分和を返却
*/
template <class T, class Iterator>
T MovingAve<T, Iterator>::operator()(Iterator first, Iterator last)
{
T sum = 0;
while ( first != last ) {
sum+=*first;
++first;
}
return sum;
}
> first とlast が代入されるという認識なのですが、間違ってますでしょうか?
間違い。
どこからどういう発想が出てきたのかよくわからないが、コンパイラは神ではないので
ソースコードを字面どおりに解釈するだけであり
transform( first, last, back_inserter(m_vec),
MovingAve<int,vector<int>::iterator >() );
4個目の引数は MovingAve というクラスの一時オブジェクトを生成している、
その際 () 指定で引数なしコンストラクタを呼んでいると解釈する。
STL アルゴリズムの使い方の理解法。とりあえず C++ ソースの <algorithm> を見る。
たいてい <algorithm> の中からさらに別のファイルを呼んでいるので追いかける。
そうすると、数個追っかけると今使いたい <algorighm> 関数のソースが見られる。
4引数 transform であれば
oit transform(iit top, iit bot, oit result, unaryop op) {
for (; top!=bot; ++top, ++result) *result = op(*top);
return result;
}
だから algorithm 中で繰り返し何度も unaryop op が呼ばれるわけだ。
ここで op に渡されるのは既に iterator ではないわけで
<algorithm> 系関数の中で使われる unary/binary operator にしたいのであれば
T MovingAve<T, Iterator>::operator()(Iterator first, Iterator last)
では不適合
逆に first last 両方を渡してほしい関数を作りたいのであれば
その関数は transform や copy や accumulate 等と同格、
つまり algorithm 関数を自作することになる。
あと iterator を引数に受け取る関数は & 参照にしないほうがいいぞ。
http://homepage1.nifty.com/MADIA/vc/vc_bbs/200711/200711_07110006.html
tetrapod さん大変よく分かりました、ありがとうございます。
http://www.kab-studio.biz/Programing/Codian/STL/02.html
ここにtransform の解説として
std::transform() は、関数オブジェクトを使用しないと使えないアルゴリズムのひとつ
です。このアルゴリズムは、第1・2引数に渡された配列を第4引数の関数オブジェクト
へと渡して、その結果を第3引数の配列へと格納するという機能を持っています。つまり
「配列を関数オブジェクトに掛ける」という機能のみを持ったアルゴリズムということで
すね。
この文を読んで、勝手に解釈し「第1・2引数に渡された配列・・・」これを
第4引数の関数オブジェクトへ渡せばいいという、頓珍漢なことをやっていました。