スニペットを検討してください:
# include <iostream>
# include <boost/scoped_ptr.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/function.hpp>
# include <boost/array.hpp>
# include <boost/asio.hpp>
# include <boost/thread.hpp>
# include <boost/thread/locks.hpp>
# include <boost/bind.hpp>
# include <boost/noncopyable.hpp>
# include <boost/variant.hpp>
class DataLink {};
class Metadata {};
class Image {};
typedef boost::function<void( DataLink const&, Metadata const& , Image const& )> Handler ;
typedef boost::function<void( Metadata const& , Image const& )> Handler2 ;
typedef boost::function<void( Image const& )> Handler3 ;
typedef boost::variant<DataLink, Metadata, Image> Variant;
enum callbackHandler { link_enum, meta_enum, image_enum };
class Worker {
Handler callBack ;
//Handler2 callBack2 ;
//Handler3 callBack3 ;
DataLink dlink;
Metadata meta ;
Image img ;
callbackHandler handlerEnum ;
public :
Worker ( const Handler& handler )
: callBack ( handler )
{}
//Worker ( const Handler2& handler )
//: callBack2 ( handler )
// {}
//Worker ( const Handler3& handler )
//: callBack3 ( handler )
// {}
void Image ( ) {
// update the img object
// invoke call back
handlerEnum = image_enum ;
//const std::type_info& xxx = callBack.target_type();
//std::cout << xxx.raw_name() << std::endl;
callBack ( dlink, meta, img ) ;
}
void Metadata ( ) {
// update the meta object
// invoke call back
handlerEnum = meta_enum ;
callBack ( dlink, meta, img ) ;
}
void Dlink ( ) {
// update the link object
// invoke call back
handlerEnum = link_enum ;
callBack ( dlink, meta, img ) ;
}
callbackHandler getHandlerType() { return handlerEnum ; }
};
class Foo {
Worker *ptrWorker ;
public :
Foo ()
: ptrWorker( 0 )
{}
void callback ( DataLink const& d, Metadata const& m , Image const& i ) {
callbackHandler tt = ptrWorker->getHandlerType();
if ( tt == image_enum ) {
std::cout << "Image object " << std::endl;
}
if ( tt == meta_enum ) {
std::cout << "Meta object " << std::endl;
}
if ( tt == link_enum ) {
std::cout << "Link object " << std::endl;
}
}
bool start () {
ptrWorker = new ( std::nothrow ) Worker ( boost::bind ( &Foo::callback, this, _1, _2, _3 ) );
if ( !ptrWorker ) {
return - 1 ;
}
}
void testWorker() {
ptrWorker->Image() ;
ptrWorker->Metadata() ;
ptrWorker->Dlink() ;
}
};
int main() {
Foo f;
f.start() ;
f.testWorker() ;
std::cin.get() ;
}
コンストラクターをコメントアウトすると、Handler2 と Handler3 のサポートを追加できますが、Worker クラスのコンストラクターに渡されたハンドラーを特定する方法はありますか? 現在、メンバ関数 Metadata、Image、Dlink は「callBack」オブジェクトを使用しています。ユーザーハンドラーが別のハンドラーを渡した場合は、区別する必要があります-たとえば、Handler2
実装するために列挙型を使用する必要があるという事実は、実質的に私自身の型システム (差別的な共用体の行 - 別名、バリアント) であり、設計を少し再考する必要があることの確かな兆候でもあります。その場合、私は再設計のために開いています。クラスで定義された N-1 個のダミー ハンドラー (つまり、一度に 1 つのハンドラーのみが使用され、他のハンドラーは何もしない) を持たなければならないことは、オブジェクト モデルが混乱し、凝集度が低くなりますが、誰にもわかりません。