C++的函数也有类型。比如:
void func(int a);
上面的函数的类型是: void(int)
它可以作为模板类型参数,如同普通的类型一样:
template<typename T> Foo;
Foo<void(int)> foo;
std::function模板就有类似的用法。
我做了一个实验,设计一个函数表,但是是用模板的行式。来测试一下这个特殊的类型定义。
代码如下:
#include <array>
#include <iostream>
#include <map>
template<typename FunctionType, size_t MAX_FUNC_TYPE>
class FunctionMap
{
public:
bool RegisterFunction(size_t func_type, FunctionType* function)
{
if (nullptr == function) return false;
if (func_type >= MAX_FUNC_TYPE) return false;
if (m_function_map[func_type] != nullptr) return false;
m_function_map[func_type] = function;
return true;
}
template<typename... ParamType>
void CallFunction(size_t func_type, ParamType&&... param)
{
auto f = this->GetFunction(func_type);
if (nullptr != f)
{
f(std::forward<ParamType>(param)...);
}
}
private:
FunctionType* GetFunction(size_t func_type)
{
if (func_type >= MAX_FUNC_TYPE) return nullptr;
return m_function_map[func_type];
}
std::array<FunctionType*, MAX_FUNC_TYPE> m_function_map{};
};
void Test(int a)
{
std::cout << "Test " << a << std::endl;
}
int main()
{
enum
{
FUNC_TYPE_1,
FUNC_TYPE_2,
FUNC_TYPE_MAX,
};
FunctionMap<void(int), FUNC_TYPE_MAX> fm;
fm.RegisterFunction(FUNC_TYPE_1, [](int i) { std::cout << "Func1 called " << i << std::endl; });
fm.RegisterFunction(FUNC_TYPE_2, [](int i) { std::cout << "Func2 called " << i << std::endl; });
fm.CallFunction(FUNC_TYPE_1, 42);
fm.CallFunction(FUNC_TYPE_2, 43);
std::cin.get();
}
函数类型如同数组类型一样,不能直接作为函数参数,需要转换成指针。
CallFunction 函数这里使用了变长模板参数、万能引用+完美转发惯用法,从而实现了客户端调用接口。