ふと、TR1のrefを実装しようと思い立った。それほど面倒になるとは思わなかったのだが、恐ろしく難儀している。一体このライブラリは設計した奴は変態ではなかろうか。誰にせよ、メタプログラムを呼吸している奴に違いない。かなり難しい。
普通に部分的特殊化だけで場合分けして実装していると、同じようなコードの重複が目立ってきたので、CRTPを使うことにした。これなら簡潔に記述できる。
ところで、行き詰ったところがある。ネストされた型名、unary_functionやbinary_functionを継承しているかどうか判別するメタ関数の書き方は分かる。result_typeがあるかどうかを判別するメタ関数の書き方も分かる。しかし、以下のコードはコンパイルが通るべきなのだろうか。
#include <functional>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
struct Foo
: std::unary_function<int, void>
, std::binary_function<int, int, void>
{
typedef void result_type ;
void operator () (int x) const
{ }
void operator () (int x, int y) const
{ }
} ;
template < typename T >
void check( T x )
{
BOOST_STATIC_ASSERT(( boost::is_base_of< std::unary_function<int, void>, T >::value )) ;
BOOST_STATIC_ASSERT(( boost::is_base_of< std::binary_function<int, int, void>, T >::value )) ;
}
int main()
{
check( std::tr1::cref( Foo() ) ) ;
}
ご存知のとおり、C++には、オーバーロードと多重継承がある。したがって、クラスFooはunary_functionでもあり、binary_functionでもある。ドラフト規格では、このコードがコンパイルエラーになるべきだとは言っていない。するとこのコードはコンパイルできるべきなのだろうか。しかし、もしコンパイル可能であるべきならば、reference_wrapperでも多重継承を使わなければならない。EBCOの観点から見て、あまり好ましくないと思うのだが。
ちなみに、DinkumwareのTR1の実装は、このコードをコンパイルできない。
No comments:
Post a Comment