C++程式碼片段(一)萃取函式返回值型別,引數型別,引數個數
阿新 • • 發佈:2019-02-18
函式的型別主要集中在以下幾種
- 函式指標
- 函式物件,是一個類物件,內部過載的operator()函式是一個函式指標
- lambda,匿名函式物件,同函式物件
- function物件
後三者都是類物件,可以看成一種型別
定義基礎模板類
template <typename T>
struct function_traits;
針對函式指標進行偏特化
對於函式指標,存在兩種情況
- 直接通過decltype獲取型別
- 利用模板推導型別
int pointer_func(int a, int b) {
return a + b;
}
// decltype(pointer_func) is int (int, int)
int pointer_func(int a, int b) {
return a + b;
}
template <typename Func>
void traits_test1(Func&&) {
}
template <typename Func>
void traits_test2(Func) {
}
int main() {
// Func = int(&)(int, int)
traits_test1(pointer_func);
// Func = int(*)(int, int)
traits_test2(pointer_func);
}
不難發現,函式指標的型別為
- R(*)(Args…)
- R(&)(Args…)
- R(Args…)
其中R是函式返回值型別,Args是函式的引數列表,針對這三種進行特化
template <typename R, typename... Args>
struct function_traits_helper
{
static constexpr auto param_count = sizeof...(Args);
using return_type = R;
template <std::size_t N>
using param_type = std::tuple_element_t<N, std::tuple<Args...>>;
};
// int(*)(int, int)
template <typename R, typename... Args>
struct function_traits<R(*)(Args...)> : public function_traits_helper<R, Args...>
{
};
// int(&)(int, int)
template <typename R, typename... Args>
struct function_traits<R(&)(Args...)> : public function_traits_helper<R, Args...>
{
};
// int(int, int)
template <typename R, typename... Args>
struct function_traits<R(Args...)> : public function_traits_helper<R, Args...>
{
};
針對lambda進行偏特化
假設在main函式中定義一個匿名函式lambda,通過模板引數型別推導判斷它的型別
template <typename Func>
void traits_test(Func&&) {
}
int main()
{
auto f = [](int a, int b) { return a + b; };
// Func = main()::<lambda(int, int)> const
// Func::operator() = int(main()::<lambda(int, int)>*)(int, int) const
traits_test(f);
return 0;
}
lambda實際上是一個匿名函式物件,可以理解為內部也過載了operator()函式,所以如果將lambda整體進行推導,那麼會推匯出一個main()::
template <typename R, typename... Args>
struct function_traits_helper
{
static constexpr auto param_count = sizeof...(Args);
using return_type = R;
template <std::size_t N>
using param_type = std::tuple_element_t<N, std::tuple<Args...>>;
};
template <typename ClassType, typename R, typename... Args>
struct function_traits<R(ClassType::*)(Args...) const> : public function_traits_helper<R, Args...>
{
using class_type = ClassType;
};
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())> {};
通過std::function和std::bind繫結的函式物件和lambda型別相同,不需要額外的特化
增加const版本
針對某些可能推匯出const的增加const版本,比如上述的lambda
完整程式碼請參考這裡