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

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

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

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

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

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

Q&A

解決済

2回答

6308閲覧

ラムダ式を与えてクラスのメンバに保持させるコールバック関数を作りたい

taratail

総合スコア76

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

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

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

0グッド

0クリップ

投稿2015/10/08 07:59

編集2015/10/08 11:09

クラスにラムダ式を与えて、そのクラス内でstd::functionとして保持し、コールバック関数として機能させるようなものを実装したいと思っています。

例えば、クラス生成時にラムダ式を与えて、そのクラスが破棄されるときに呼ばれるようなものを作りたいと考えています。

また、あらゆる引数でも実行できるようにし、さらにコールバック関数が設定されていないことも考慮して、boost::none_t, std::function<void()>, std::function<void(int)>, ... という方に対応できる共用型にしようかと考えました。

具体的には以下の様なイメージのコードが成立するようにしたいです(実際はコンパイルエラーを起こします)。

どのように書くべきでしょうか。

C++

1#include <iostream> 2#include <boost/variant.hpp> 3#include <boost/none.hpp> 4#include <functional> 5 6class some_class { 7 8private: 9 using call_back_func_t = boost::variant< 10 boost::none_t, 11 std::function<void()>, 12 std::function<void(int)> 13 >; 14 15 auto some_func() { 16 boost::apply_visitor(call_back_visitor(), call_back_); 17 } 18 19 call_back_func_t call_back_; 20 21public: 22 23 struct call_back_visitor : public boost::static_visitor<> { 24 auto operator()(boost::none_t const& none) const {} 25 auto operator()(std::function<void()> func) const { func(); } 26 auto operator()(std::function<void(int)> func, int x) const { func(x); } 27 }; 28 29 some_class(call_back_func_t call_back): call_back_(call_back){} 30 ~some_class(){ some_func(); } 31 32 33}; 34 35int main() { 36 37 int x = 5; 38 39 some_class a( 40 boost::none 41 ); 42 43 { 44 some_class b( 45 []{ std::cout << "ok" << std::endl; } 46 ); 47 } 48 49 some_class c( 50 [x](){ std::cout << x << std::endl; } 51 ); 52 53 /* 54 望まれる実行結果 55 ./a.out 56 ok 57 5 58 */ 59 60}

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

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

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

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

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

yohhoy

2015/10/08 10:25

最後のcでは、ラムダキャプチャのxとラムダ引数のxと2つ指定していますが、意図したものでしょうか?キャプチャしたxがあれば引数は不要では?
taratail

2015/10/08 11:08

すみません。おっしゃるとおりで特に必要はありません。修正させていただきます。
guest

回答2

0

ベストアンサー

下記コードで要件をみたせるでしょうか。

cpp

1#include <functional> 2 3class some_class { 4public: 5 some_class() = default; 6 7 explicit some_class(std::function<void()> f) 8 : callback_(std::move(f)) {} 9 10 ~some_class() noexcept(false) 11 { callback_(); } 12 13private: 14 std::function<void()> callback_ = []{}; 15};

http://melpon.org/wandbox/permlink/Yz041bVYUteFs8P0

投稿2015/10/08 14:56

編集2015/10/08 15:07
yohhoy

総合スコア6189

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

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

taratail

2015/10/08 23:57

なるほどこのように書けばよかったのですね。求めていたものそのままです! ありがとうございます!
guest

0

struct onleaving
{
void (*func)();
onleaving( void(*f)() ) : func(f){}
~onleaving(){ func(); }
};

template<class T>
struct onleaving1
{
void (*func)(T);
T arg;
onleaving1( void(*f)(T), T a )
: func(f), arg(a){}
~onleaving1(){ func(arg); }
};

template<class... Types>
struct onleaving2
{
void (*func)( std::tuple<Types...> );
std::tuple<Types...> args;
onleaving2( void(*f)( const std::tuple<Types...>& ), Types... a )
: func(f), args( std::make_tuple(a...) ){}
~onleaving2(){ func(args); }
};

で動きます(多分)。
いろいろ調べてみましたが、私の知識ではこれ以上綺麗に書けそうにないです…すみませんorz

投稿2015/10/08 09:09

編集2015/10/08 09:45
majiponi

総合スコア1720

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

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

taratail

2015/10/08 11:07

いえいえ!ありがとうございます。 なるほどstd::tupleを使うという方法ですね。色々お調べいただいてありがとうございます。勉強になりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問