コンパイル時分岐
独自実装のintervalクラスでメンバ関数sin()を実装した。しかし、ジェネリックなコードが書きたい。 sin(x)とかいたとき、intervalならx.sin()を、でなければstd::sin(x)を呼び出したい。 こんなときどうすれば良い?
プライマリテンプレートと明示的特殊化を使って、コンパイル時に条件分岐を行えばよい。
#include <cmath>
#include <type_traits>
struct interval
{
double sin( ) const
{
// unimplemented
return 0.0 ;
}
} ;
// プライマリーテンプレート
// デフォルトの実装
template < typename T >
struct dispatch
{
static double invoke( T const & value )
{
return std::sin( value ) ;
}
} ;
// interval型に対して明示的特殊化
template < >
struct dispatch<interval>
{
static double invoke( interval const & value )
{
return value.sin() ;
}
} ;
template < typename T >
void f( T const & x )
{
double s = dispatch<T>::invoke(x) ;
}
int main()
{
double d = 1.0 ;
f( d ) ;
interval i ;
f( i ) ;
}
以下のように書くこともできる。
struct generic_sin
{
template < typename T >
static double invoke( T const & value )
{
return std::sin( value ) ;
}
} ;
struct interval_sin
{
static double invoke( interval const & value )
{
return value.sin() ;
}
} ;
template < typename T >
using dispatch = std::conditional_t< std::is_same<T, interval>::value,
interval_sin, generic_sin > ;