decltypeでboost::bindに渡すファンクタの戻り値を指定できないか頑張る(conceptGCC)

boost::bindは、ファンクタを渡した場合に戻り値の推測することができないので、
std::function系を継承してないファンクタを渡す場合は下のようにファンクタの中で戻り値をresult_typeとしてtypedefするか

#include <iostream>
#include <string>
#include <boost/bind.hpp>

struct Functor
{
	typedef void result_type;

	result_type operator()(std::string str){
		std::cout << str << std::endl;
	}
};


int main()
{
	boost::bind(Functor(),"Hello")();

	return 0;
}

下のようにテンプレート引数として渡す必要がある

int main()
{
	boost::bind<void>(Functor(),"Hello")();

	return 0;
}


まあ、std::function系をちゃんと継承するのであれば

#include <iostream>
#include <string>
#include <functional>
#include <boost/bind.hpp>

struct Functor : std::unary_function< std::string , void >
{
	result_type operator()(argument_type str){
		std::cout << str << std::endl;
	}
};


int main()
{
	boost::bind(Functor(),"Hello")();

	return 0;
}

こんな感じにもできる



conceptGCCでdecltypeが使えるようなので、
decltypeを使って上手いこと書けないかやってみると

#include <iostream>
#include <string>
#include <boost/bind.hpp>

struct Functor
{
	void operator()(std::string str){
		std::cout << str << std::endl;
	}
};


int main()
{
	boost::bind<decltype(Functor()(std::string()))>(Functor(),"Hello")();

	return 0;
}

とりあえずこれで動いた
でもこれだとコーディング量が増えただけなような・・・



result_typeを上手いことdecltypeを使って定義してやれないかいろいろ試したんだけど、なかなか上手くいかず
引数のないファンクタならとりあえず動きそうな物が出来た↓

#include <iostream>
#include <string>
#include <boost/bind.hpp>

struct SayHello
{
	void operator()(){
		std::cout << "Hello" << std::endl;
	}
};

template <typename Functor>
struct FunctorWrapper
{
	typedef decltype(Functor()()) result_type;

	void operator()(){
		Functor()();
	}
};

int main()
{
	boost::bind(FunctorWrapper<SayHello>())();//バインドする引数もないのにバインド

	return 0;
}

すごい、何の役にも立たない!
なんか確実に上手いことやる方法はあるんだろうけどなー


ということで、Modern C++ Designがすごく読みたいです。