おとといのエントリで書いた演算子を、汎用的に使えるようにしてみました。
// Operators.h #ifndef OPERATORS_H #define OPERATORS_H template<typename T, typename U> struct Operator { explicit Operator(const T& lhs) : lhs(lhs) {} const T& lhs; }; template<typename T, typename U> inline Operator<T, U> operator % (const T& lhs, U) { return Operator<T, U>(lhs); } #endif//OPERATORS_H
これを使っていろいろやってみたいと思います。
power
x ** y
こんなふうに書けるとうれしいんですが、百歩ほどゆずって
x %power% y
というのをやってみます。
#include <iostream> #include <cmath> #include "Operators.h" enum POWER { power }; inline double operator % (const Operator<double, POWER>& op, int rhs) { return pow(op.lhs, rhs); } int main(int, char* []) { for(int i = -3; i <= 3; ++i) { std::cout << "5 power " << i << " = " << (5.0 %power% i) << "\n"; } return 0; }
実行してみるとこんな感じ。
5 power -3 = 0.008 5 power -2 = 0.04 5 power -1 = 0.2 5 power 0 = 1 5 power 1 = 5 5 power 2 = 25 5 power 3 = 125
5 %power% i
と書けるといいんですが、型が合わなくなるのでコンパイルできません。詰めが甘いです。
times
Rubyでいうところの
sum = 0 10.times do |n| sum += n end puts "0+1+...+9 = #{sum}"
これをやってみます。
#include "Operators.h" enum TIMES { times }; template<typename Func_T> inline void operator % (const Operator<int, TIMES>& op, Func_T rhs) { for(int i = 0; i < op.lhs; ++i) { rhs(i); } } // つづく...
ここまでがtimes
を実現するためのコード。
以下が利用例。
// ...つづき #include <functional> #include <iostream> struct Summater : public std::unary_function<int, void> { int& sum; explicit Summater(int& sum) : sum(sum) {} void operator () (int n) { sum += n; } }; int main(int, char* []) { int sum = 0; 10 %times% Summater(sum); std::cout << "0+1+...+9 = " << sum << std::endl; return 0; }
不格好だけど、できた。できた…と言っていいんじゃないかな?
each
times
ができたんならeach
もできるだろう、ということで迷わず前進。
#include <iostream> #include <vector> #include <set> #include <functional> #include "Operators.h" enum EACH { each }; template<typename T, typename Func_T> inline void operator % (const Operator<T, EACH>& op, Func_T rhs) { for(typename T::const_iterator i = op.lhs.begin(); i != op.lhs.end(); ++i) { rhs(*i); } } struct Writer : public std::unary_function<int, void> { void operator () (int n) { std::cout << n << std::endl; } }; int main(int, char* []) { Writer writer; std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); // std::vector を each v %each% writer; std::set<int> s; s.insert(1); s.insert(2); s.insert(3); // std::set だって each s %each% writer; return 0; }
総括
書いていて楽しいけれど、効果的かどうかは疑問。効果の割にコストが高過ぎるかも。