こういうことができる。
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