std::functionにメンバ関数を入れてやるにはどうすればいいのやらと試行錯誤。
まずは非メンバ関数の場合
こちらは悩まずこんな感じでいけた。
std::function 非メンバ関数版
#include <iostream> #include <unordered_map> #include <functional> template <typename T> T plus(T p1, T p2) { return p1 + p2; } template <typename T> T minus(T p1, T p2) { return p1 - p2; } template <typename T> T multi(T p1, T p2) { return p1 * p2; } template <typename T> T div(T p1, T p2) { return p1 / p2; } template <typename T> class Func { private: T operatnd1_; T operatnd2_; std::unordered_map< std::string, std::function<T (T, T)> > optr_; public: Func() { // とりあえず下記だけサポート optr_["+"] = plus<T>; optr_["-"] = minus<T>; optr_["*"] = multi<T>; optr_["/"] = div<T>; }; T call(std::string ope, T p1, T p2) { // 例外処理しない(手抜き) return optr_[ope](p1, p2); } }; int main() { Func<double> f; std::cout << f.call("+", 1, 2) << '\n'; std::cout << f.call("-", 1, 2) << '\n'; std::cout << f.call("*", 1, 2) << '\n'; std::cout << f.call("/", 1, 2) << '\n'; return 0; }
一応出力結果
3 -1 2 0.5
std::function メンバ関数版
#include <iostream> #include <unordered_map> #include <functional> template <typename T> class Func { private: T operatnd1_; T operatnd2_; std::unordered_map< std::string, //std::function<T (Func<T>::*)(T, T)> // こうじゃなくて単純にT (T, T) std::function<T (T, T)> > optr_; T plus(T p1, T p2) { return p1 + p2; } T minus(T p1, T p2) { return p1 - p2; } T multi(T p1, T p2) { return p1 * p2; } T div(T p1, T p2) { return p1 / p2; } public: Func() { // mem_fnじゃなくてbindを使うっぽい using namespace std::placeholders; // とりあえず下記だけサポート // 自クラス内のメソッド指定の場合はthisを指定 // 引数が複数ある場合はplaceholdersで指定してやる optr_["+"] = std::bind(&Func<T>::plus, this, _1, _2); optr_["-"] = std::bind(&Func<T>::minus, this, _1, _2); optr_["*"] = std::bind(&Func<T>::multi, this, _1, _2); optr_["/"] = std::bind(&Func<T>::div, this, _1, _2); }; T call(std::string ope, T p1, T p2) { // 例外処理しない(手抜き) return optr_[ope](p1, p2); } }; int main() { Func<double> f; std::cout << f.call("+", 1, 2) << '\n'; std::cout << f.call("-", 1, 2) << '\n'; std::cout << f.call("*", 1, 2) << '\n'; std::cout << f.call("/", 1, 2) << '\n'; return 0; }
同じだけど一応出力結果
3 -1 2 0.5
bind使って_1,_2を指定してやればいいのかとわかり解決。
ラムダを使いたいところですが、テンプレートの場合はラムダダメだった気がする……。
メンバ関数ポインタ版で書くと…カオスになるからやめよ(´・ω・`)
と思ったけど書いてみた。
メンバ関数ポインタ版
#include <iostream> #include <unordered_map> template <typename T> class Func { private: T operatnd1_; T operatnd2_; // メンバ関数ポインタにPFUNCという名前を付ける typedef T (Func<T>::*PFUNC)(T, T); std::unordered_map< std::string, PFUNC > optr_; T plus(T p1, T p2) { return p1 + p2; } T minus(T p1, T p2) { return p1 - p2; } T multi(T p1, T p2) { return p1 * p2; } T div(T p1, T p2) { return p1 / p2; } public: Func() { optr_["+"] = &Func<T>::plus; optr_["-"] = &Func<T>::minus; optr_["*"] = &Func<T>::multi; optr_["/"] = &Func<T>::div; }; T call(std::string ope, T p1, T p2) { return (this->*optr_[ope])(p1, p2); } }; int main() { Func<double> f; std::cout << f.call("+", 1, 2) << '\n'; std::cout << f.call("-", 1, 2) << '\n'; std::cout << f.call("*", 1, 2) << '\n'; std::cout << f.call("/", 1, 2) << '\n'; return 0; }
どうにもFunc
やら->*
やらがうーん(´・ω・`)
参考