質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

4257閲覧

C++ 関数の引数に関数を渡せますか?

opyon

総合スコア1009

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2018/11/11 20:33

編集2018/11/12 07:54

###解決!
回答くださった方ありがとうございました。
どの回答もとても参考になりました。
具体的なコードもあったので分かりやすかったです。

実際頻繁に使うのか?と言われると可読性や冗長になることもあるのでなんとも言えませんが、
マクロで出来ないことが実現しやすいし出来ることの可能性はかなり広がったと思います。

###サンプルコード(早速使ってみた)

C++

1#include <bits/stdc++.h> 2 3bool is_odd(int x) 4{ 5 return x % 2; 6} 7 8unsigned fibo(unsigned n) 9{ 10 if (n < 2) 11 { 12 return 1; 13 } 14 return fibo(n - 1) + fibo(n - 2); 15} 16 17template <typename T1, typename T2, typename Func1, typename Func2, typename T3> 18void yn(const T1 &e1, const T2 &e2, const Func1 func1, const Func2 func2, const T3 &fe1) 19{ 20 auto ret1 = func2(fe1); 21 auto ret2 = (func1(ret1) ? e1 : e2); 22 std::cout << "ret1:" << ret1 << " ret2:" << ret2 << "\n"; 23} 24 25// 上記では出力するために分けていますが入れ子でも使えますし 26// 可変長でも使えそうです 27// ret = (func1(func2(fe1)) ? e1 : e2); 28 29int main() 30{ 31 // フィボナッチ数列のi項の奇数偶数判定 32 for (unsigned i = 0; i < 20; i++) 33 { 34 std::cout << "i:" << i << " "; 35 yn("odd", "even", is_odd, fibo, i); 36 } 37 getchar(); 38 return 0; 39} 40 41// 出力サンプル 42// i:0 ret1:1 ret2:odd 43// i:1 ret1:1 ret2:odd 44// i:2 ret1:2 ret2:even 45// i:3 ret1:3 ret2:odd 46// i:4 ret1:5 ret2:odd 47// i:5 ret1:8 ret2:even 48// i:6 ret1:13 ret2:odd 49// i:7 ret1:21 ret2:odd 50// i:8 ret1:34 ret2:even 51// i:9 ret1:55 ret2:odd 52

###追記
lambda式を引数として受け取る関数の自作はできますか?
こちらの回答が参考になりそうです。
また時間のある時に作ってみます。

###知りたいこと
関数の引数に関数を渡せますか?

###現状
前の質問の@LouiS0616さんの回答 で頂いたコードをヒントにこんなこと出来ると便利そうだなと思い質問させていただいています。

例えばこの func1(e1) を引数も指定して渡せたら汎用的に使えて便利そうです。
分かりにくいかも知れませんが例えば func1()func2() を指定して切り替えられますか?
yn(func1(3), "yes", "no");
yn(func2(2), "yes", "no");
例えが悪いのでこれだと結果が渡されて期待通りの結果が出ますがイメージが伝わればと思います。

どのようにしたら出来るのか検討もつかないので出来るか出来ないかだけでもご教示頂けると幸いです。

C++

1#include <bits/stdc++.h> 2 3bool func1(int x) 4{ 5 return x % 2; 6} 7 8bool func2(int x) 9{ 10 return (x + 1) % 2; 11} 12 13template <typename T1, typename T2, typename T3> 14void yn(const T1 &e1, const T2 &e2, const T3 &e3) 15{ 16 auto ret = (func1(e1) ? e2 : e3); 17 std::cout << ret << "\n"; 18} 19 20int main() 21{ 22 yn(3, "yes", "no"); 23 getchar(); 24 return 0; 25} 26

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こんにちは。

std::bindを使う方法もありますよ。引数の数が異なっても使えます。

C++

1#include <iostream> 2#include <functional> 3 4bool func1(int x) 5{ 6 return x % 2; 7} 8 9bool func2(int x) 10{ 11 return (x + 1) % 2; 12} 13 14bool func3(int x, int y) 15{ 16 return (x + y) % 2; 17} 18 19template <typename T1, typename T2, typename T3> 20void yn(const T1 &e1, const T2 &e2, const T3 &e3) 21{ 22 auto ret = (e1() ? e2 : e3); 23 std::cout << ret << "\n"; 24} 25 26int main() 27{ 28 yn(std::bind(func1, 3), "yes", "no"); 29 yn(std::bind(func2, 2), "yes", "no"); 30 yn(std::bind(func3, 2, 3), "yes", "no"); 31 getchar(); 32 return 0; 33}

引数の順序を変える必要がありますが、可変長引数テンプレートにする手もあります。

C++

1#include <iostream> 2#include <functional> 3 4bool func1(int x) 5{ 6 return x % 2; 7} 8 9bool func2(int x) 10{ 11 return (x + 1) % 2; 12} 13 14bool func3(int x, int y) 15{ 16 return (x + y) % 2; 17} 18 19template <typename T2, typename T3, typename Func, typename... T1> 20void yn(const T2 &e2, const T3 &e3, Func func, T1... e1) 21{ 22 auto ret = (func(e1...) ? e2 : e3); 23 std::cout << ret << "\n"; 24} 25 26int main() 27{ 28 yn("yes", "no", func1, 3); 29 yn("yes", "no", func2, 2); 30 yn("yes", "no", func3, 2, 3); 31 getchar(); 32 return 0; 33}

投稿2018/11/12 02:19

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/11/12 07:59

回答ありがとうございます。 std::bindもシンプルに書けそうで良いですね。 具体的なコードがイメージしてた通りでとても分かりやすく参考になりました。
guest

0

引数一つ増やせば出来るんじゃないかなぁ。デフォルトの関数を設定する方法の説明は割愛しますが。

C++

1#include <bits/stdc++.h> 2 3bool func1(int x) { return x % 2; } 4 5bool func2(int x) { return (x + 1) % 2; } 6 7struct functor { 8 bool operator()(int x) const { return x % 2; }; 9}; 10 11template <typename T1, typename T2, typename T3, typename Func> 12void yn(const T1 &e1, const T2 &e2, const T3 &e3, const Func &func) { 13 auto ret = (func(e1) ? e2 : e3); 14 std::cout << ret << "\n"; 15} 16 17int main() { 18 yn(3, "yes", "no", func1); 19 yn(3, "yes", "no", func2); 20 21 // 関数オブジェクト 22 yn(3, "yes", "no", functor()); 23 24 // lambda式 25 yn(3, "yes", "no", [](int x) -> bool { return x % 2; }); 26 27 getchar(); 28 return 0; 29}

投稿2018/11/11 23:48

tachikoma

総合スコア3601

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/11/12 07:56

回答ありがとうございます。 operator()やlambda式などの書き方もあることを知りとても参考になりました。
guest

0

できます。
例としては std::qsort は 大小比較関数を引数にわたすようになってます。

https://ja.cppreference.com/w/cpp/algorithm/qsort

参考

  • C++で構造体やクラスをソートする方法まとめ

https://qiita.com/arcslab123/items/7cd217cc5fafef700dff

追記:
偶数/奇数判定関数を作成し、それを関数の渡すような例を作成してみました。
g.cpp

g++

1#include <iostream> 2 3typedef bool (FUNC)(int); 4 5bool is_even(int x) { 6 return x % 2; 7} 8 9bool is_odd(int x) { 10 return (x + 1) % 2; 11} 12 13void yn(FUNC func, const int x, std::string s_ok, std::string s_ng) { 14 std::string ret = func(x) ? s_ok : s_ng; 15 std::cout << ret << "\n"; 16} 17 18int main() { 19 yn(is_even, 1, "yes", "no"); 20 yn(is_odd, 1, "yes", "no"); 21 return 0; 22}

実行例:
イメージ説明

投稿2018/11/11 22:07

編集2018/11/12 12:30
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/11/11 22:25

回答ありがとうございます。 なるほど確かにsort関連で使ったことがありました。 汎用的な関数を自作するならどうすればいいのか模索中です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問