[C++]for each(2) のコメントより、
# re: [C++]for each(2) 2007/09/26 11:54 επιστημη
std::vector<std::string> v;
...
int i = 0;
// loop_countはコンテナとint&を受け取る。++のついでにint&を++する。
for each ( std::string value in loop_count(v,i)) {
std::cout << '[' << i << "] = " << value << std::endl;
}
なんてのはいかがざんしょ。
なるほど!
ということで実装してみました。
template<class TIter, class TValue, class TCount>
class loop_ref_count_iterator
{
TCount& count;
public:
TIter iter;
loop_ref_count_iterator(TIter iter_, TCount& count_)
: iter(iter_), count(count_) { }
loop_ref_count_iterator& operator++()
{
++iter;
++count;
return *this;
}
bool operator!=(const loop_ref_count_iterator& right) const
{
return (iter != right.iter);
}
TValue operator*() const
{
return *iter;
}
};
template<class TColl, class TCount>
class loop_ref_count_iteratable
{
private:
TColl& coll;
TCount& count;
public:
typedef typename TColl::iterator iterator;
typedef typename TColl::value_type value_type;
loop_ref_count_iterator<iterator, value_type, TCount> begin() const
{
return loop_ref_count_iterator<iterator, value_type, TCount>(coll.begin(), count);
}
loop_ref_count_iterator<iterator, value_type, TCount> end() const
{
return loop_ref_count_iterator<iterator, value_type, TCount>(coll.end(), count);
}
loop_ref_count_iteratable(TColl& coll_, TCount& count_)
: coll(coll_), count(count_) { }
};
template<class TColl, class TCount>
loop_ref_count_iteratable<TColl, TCount> loop_count(TColl& iteratable, TCount& count)
{
return loop_ref_count_iteratable<TColl, TCount>(iteratable, count);
}
テスト
std::vector<std::string> strs;
strs.push_back("aiueo");
strs.push_back("hogehoge");
strs.push_back("fugafuga");
int i = 0;
for each (std::string str in loop_count(strs, i))
{
std::cout << "strs[" << i << "] = " << str << std::endl;
}
for each (std::string str in loop_count(strs, i))
{
std::cout << "strs[" << i << "] = " << str << std::endl;
}
struct reverse
{
int& value;
reverse(int& n) : value(n) { }
void operator++() { value -= 2; }
};
for each (std::string str in loop_count(strs, reverse(i)))
{
std::cout << "strs[" << i << "] = " << str << std::endl;
}
結果
strs[0] = aiueo
strs[1] = hogehoge
strs[2] = fugafuga
strs[3] = aiueo
strs[4] = hogehoge
strs[5] = fugafuga
strs[6] = aiueo
strs[4] = hogehoge
strs[2] = fugafuga
operator++() さえ定義されていれば何でも受け付けるようにしてみましたw
便利便利~w
で、もいっこ思いつきました。
カウントだけしか行わないイテレータ。
template<class TIter>
class loop_count_only_iterator
{
int count;
public:
TIter iter;
loop_count_only_iterator(TIter iter_, int count_ = 0)
: iter(iter_), count(count_) { }
loop_count_only_iterator& operator++()
{
++iter;
++count;
return *this;
}
bool operator!=(const loop_count_only_iterator& right) const
{
return (iter != right.iter);
}
int operator*() const
{
return count;
}
};
template<class TColl>
class loop_count_only_iteratable
{
private:
TColl& coll;
public:
typedef typename TColl::iterator iterator;
typedef typename TColl::value_type value_type;
loop_count_only_iterator<iterator> begin() const
{
return loop_count_only_iterator<iterator>(coll.begin());
}
loop_count_only_iterator<iterator> end() const
{
return loop_count_only_iterator<iterator>(coll.end());
}
loop_count_only_iteratable(TColl& coll_)
: coll(coll_) { }
};
template<class TColl>
loop_count_only_iteratable<TColl> loop_count_only(TColl& iteratable)
{
return loop_count_only_iteratable<TColl>(iteratable);
}
テスト
std::string str = "aiueo";
std::cout << str << std::endl;
for each (int n in loop_count_only(str))
{
std::cout << n;
}
std::cout << std::endl;
結果
aiueo
01234
何という無意味w
追記:
どうやら operator*() で TValue& さえ返せば、書き込み可能な for each が作れるようです。
template<class TIter, class TValue>
class loop_writable_iterator
{
public:
TIter iter;
loop_writable_iterator(TIter iter_)
: iter(iter_) { }
loop_writable_iterator& operator++()
{
++iter;
return *this;
}
bool operator!=(const loop_writable_iterator& right) const
{
return (iter != right.iter);
}
TValue& operator*() const
{
return *iter;
}
};
template<class TColl>
class loop_writable_iteratable
{
private:
TColl& coll;
public:
typedef typename TColl::iterator iterator;
typedef typename TColl::value_type value_type;
loop_writable_iterator<iterator, value_type> begin() const
{
return loop_writable_iterator<iterator, value_type>(coll.begin());
}
loop_writable_iterator<iterator, value_type> end() const
{
return loop_writable_iterator<iterator, value_type>(coll.end());
}
loop_writable_iteratable(TColl& coll_)
: coll(coll_) { }
};
template<class TColl>
loop_writable_iteratable<TColl> loop_writable(TColl& iteratable)
{
return loop_writable_iteratable<TColl>(iteratable);
}
テスト
std::vector<int> vec;
vec.push_back(8);
vec.push_back(9);
vec.push_back(3);
for each (int& n in loop_writable(vec))
{
n *= 2;
}
for each (int n in vec)
{
std::cout << n << std::endl;
}
結果
16
18
6
これは便利かも……。