推导函数对象参数类型

Deduce function object argument types

给定一组参数类型和一个函数对象,可以用 decltype 推导出 return 类型。如何推断参数类型?

对于函数指针,return 和参数类型都可以使用有趣的模式匹配语法推导出来。例如,这是一个愚蠢的程序,它使用推导的参数类型打印出描述函数指针的 return 和参数类型的字符串。

#include <iostream>
#include <string>

using std::string;

template<class T>
string type_str();

template<>
string type_str<int>() { return "int"; }

template<>
string type_str<char>() { return "char"; }

string arg_types_str()
{
    return "";
}

template<class T>
string arg_types_str()
{
    return type_str<T>();
}

template<class T, class U, class... Args>
string arg_types_str()
{
    return type_str<T>() + ", " + arg_types_str<U, Args...>();
}

template<class R, class... Args>
void print_fptr_type(R (*fptr)(Args...))
{
    std::cout << type_str<R>() << " (*)(" << arg_types_str<Args...>() << ")" << std::endl;
}

int main()
{
    int (*fptr)(char, int);
    print_fptr_type(fptr);
}

输出:

int (*)(char, int)

Live demo.

是否可以编写类似于示例的程序,而不是打印函数对象的 return 和参数类型?

似乎对于只有一个 operator() 的函数对象,原则上可以明确地推导参数类型。

是的,可以做到。该策略类似,但对于函数对象,它是一个两阶段过程。首先获取指向operator()的成员函数指针,然后可以使用类似的模式匹配方法进行类型推导。

Live demo.

新程序的关键部分是:

template<class T, class R, class... Args>
void print_memfptr_types(R (T::*memfptr)(Args...))
{
    std::cout << type_str<R>() << " (" << type_str<T>() << "*)(" << arg_types_str<Args...>() << ")" << std::endl;
}

template<class T, class R, class... Args>
void print_cmemfptr_types(R (T::*memfptr)(Args...))
{
    std::cout << type_str<R>() << " (const " << type_str<T>() << "*)(" << arg_types_str<Args...>() << ")" << std::endl;
}

template<class T>
void print_fnc_obj_types(T&)
{
    print_memfptr_types(&T::operator());
}

template<class T>
void print_fnc_obj_types(const T&)
{
    print_cmemfptr_types(&T::operator());
}