std::function
「バイナリ区切り」(動的ライブラリ、「不透明」API など) でない限り、通常、値で受け入れることはお勧めできません。関数が実際にstd::function
by 値を取る場合、(関数がまったくオーバーロードされている場合) オーバーロードの問題を回避するために、オブジェクトを作成するのは呼び出し元の負担になることがよくあります。
std::function
ただし、テンプレートを作成したため、型消去の利点のために (パラメーター型として) を使用していない可能性があります。やりたいことが任意のファンクターを検査することである場合、そのためのいくつかの特性が必要です。たとえば、Boost.FunctionTypes には や などの特性がresult_type
ありparameter_types
ます。最小限の機能的な例:
#include <functional>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_type.hpp>
template<typename Functor>
void test(Functor functor) // accept arbitrary functor!
{
namespace ft = boost::function_types;
typedef typename ft::result_type<Functor>::type result_type;
typedef ft::parameter_types<Functor> parameter_types;
typedef typename boost::mpl::push_front<
parameter_types
, result_type
>::type sequence_type;
// sequence_type is now a Boost.MPL sequence in the style of
// mpl::vector<int, double, long> if the signature of the
// analyzed functor were int(double, long)
// We now build a function type out of the MPL sequence
typedef typename ft::function_type<sequence_type>::type function_type;
std::function<function_type> function = std::move(functor);
}
最後に、多相ファンクターでは機能しないため、一般的なケースではファンクターの内省 (つまり、結果の型と引数の型を調べること) はお勧めしません。いくつかのオーバーロードを検討してくださいoperator()
。その場合、「正規の」結果タイプまたは引数タイプはありません。C++11 では、任意の種類のファンクターを「積極的に」受け入れるか、SFINAE などの手法を使用して、またはstatic_assert
必要に応じてそれらを制約し、後で (パラメーターが利用可能な場合)特定のセットstd::result_of
の結果の型を検査するために使用することをお勧めします。引数の. 前もって制約することが望ましいのは、目的がファンクタをたとえば のコンテナに格納することである場合ですstd::function<Sig>
。
前の段落の意味を理解するには、上記のスニペットをポリモーフィック ファンクターでテストするだけで十分です。