こういうことができる。
void f() { std::cout << "f" << std::endl ; } void g() { std::cout << "g" << std::endl ; } int main() { std::function< void ( void ) > func( &f ) ; func() ; // f *func.target< void (*)(void) >() = &g ; func() ; // g }
誰が使うんだろう。
追記:これだけだと、誤解を招きそうなので、以下のコードを補足しておく。
void f() { std::cout << "f" << std::endl ; } void g() { std::cout << "g" << std::endl ; } struct h { void operator ()(void){} ; } ; int main() { std::function< void ( void ) > func( &f ) ; func() ; // f *func.target< void (*)(void) >() = &g ; func() ; // g func = h() ; // 実行時エラー、型が合わない *func.target< void (*)(void) >() = &g ; }
一応、std::function経由で呼び出すには、格納されている型を実行時に判断しなければならない。そのため、すでに格納されている型が分かっているのならば、中身を取り出すことで、そのような実行時チェックを、中身を取り出す際の一回で済ませることができる。これは、変更をしないと保証できるstd::functionのオブイェクトに対し、何百万回もoperator ()を呼び出す際に、有効であろう。そんなケースはあまりないと思うが。
void f( std::function < int (int) > f ) { // 1000000回の実行時チェックが必要 for ( int i = 0 ; i != 1000000 ; ++i ) { f(i) ; } } void g( std::function < int (int) > f ) { // fには関数ポインターが入っていると分かっている auto func = *f.target< int (*)(int) >() ; // 実行時チェックはいらない for ( int i = 0 ; i != 1000000 ; ++i ) { func(i) ; } }
もちろん、関数gを以下のように呼び出した場合、実行時エラーになる。
struct Foo { int operator ()(int) const { return 0 ; } } ; int main() { f( Foo() ) ; // OK g( Foo() ) ; // エラー }
targetは危険である。規格を読んでstd::functionを実装した者でない限り、targetを使ってはいけない。つまり、私は使う資格がある。使いたいとは思わないが。
なぜならば、gは仮引数fの中身の型が、関数ポインターであることを前提にしているからである。
No comments:
Post a Comment