次のスニペットが役立つ場合があります。
std::function
これにより、 aが取る引数の数が得られます
template <typename Signature>
struct count_args;
template <typename Ret, typename... Args>
struct count_args<std::function<Ret(Args...)>> {
static constexpr size_t value = sizeof...(Args);
};
たとえば、次のコードはコンパイルされます (clang 3.2、gcc 4.7.2、および icc 13.1.0)。
static_assert(count_args<std::function<void() >>::value == 0, "Ops!");
static_assert(count_args<std::function<void(int) >>::value == 1, "Ops!");
static_assert(count_args<std::function<void(int, int)>>::value == 2, "Ops!");
私が理解している限り、正しい数の引数を渡して関数オブジェクトを呼び出したいと思いますよね? 次に、各引数に対して、その型に変換可能な値を提供する必要があります。この一般性による解決は非常に困難です (または不可能ですらあります)。したがって、2 つの代替案を提示します。
1各引数は、その型の値初期化オブジェクトです。(これはecatmur が提案したものです。)
template <typename Ret, typename... Args>
Ret call(const std::function<Ret(Args...)>& f) {
return f(Args{}...); // for the intel compiler replace {} with ()
}
2固定値が与えられ、すべての引数はこの値から暗黙的に初期化されます。
template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<sizeof...(Args) == sizeof...(Vals), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val&, const Vals&... vals) {
return f(vals...);
}
template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<(sizeof...(Args) > sizeof...(Vals)), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val& val, const Vals&... vals) {
return call(f, val, val, vals...);
}
3 つのオーバーロードは明確であり、次の例に示すように使用できます。
{
std::function<char()> f = []() -> char {
std::cout << "f() ";
return 'A';
};
std::cout << call(f) << std::endl; // calls f()
std::cout << call(f, 0) << std::endl; // calls f()
}
{
std::function<char(int)> f = [](int i) -> char {
std::cout << "f(" << i << ") ";
return 'B';
};
std::cout << call(f) << std::endl; // calls f(0)
std::cout << call(f, 1) << std::endl; // calls f(1)
}
{
std::function<char(int, int)> f = [](int i, int j) -> char {
std::cout << "f(" << i << "," << j << ") ";
return 'C';
};
std::cout << call(f) << std::endl; // calls f(0, 0)
std::cout << call(f, 2) << std::endl; // calls f(2, 2)
}