问题描述
我试图理解这段代码 并且我在此主题上找到了更多 SO 内容.
I am trying to understand this code and I have found some more SO content on this topic.
紧凑形式:
#include <tuple>
namespace sqlite {
namespace utility {
template<typename> struct function_traits;
template <typename Function>
struct function_traits : public function_traits<
decltype(&Function::operator())
> { };
template <
typename ClassType,
typename ReturnType,
typename... Arguments
>
struct function_traits<
ReturnType(ClassType::*)(Arguments...) const
> {
typedef ReturnType result_type;
template <std::size_t Index>
using argument = typename std::tuple_element<
Index,
std::tuple<Arguments...>
>::type;
static const std::size_t arity = sizeof...(Arguments);
};
}
}
这让我了解了该语言的指向成员函数的指针特性,并且在这一点上我很清楚如何使用函数特征(很简单,我不仅可以提取返回类型,还可以提取参数甚至参数的类型),但我一直在理解 为什么 这有效,或者为什么它甚至可以工作..
This led me to learn about the pointer-to-member-function feature of the language, and it's pretty clear to me at this point how to use the function traits (it's fairly straightforward that I can pull out not only the return type but the arity and even the types of the arguments) but I have gotten stuck in understanding why this works, or indeed why it is even possible for it to work...
推荐答案
让我们一点一点地分解一切.
Let's break everything down piece by piece.
template<typename> struct function_traits;
这是主要的模板声明,使用单个模板参数声明模板类.
That is the primary template declaration, declaring a template class with a single template parameter.
template <typename Function>
struct function_traits : public function_traits<
decltype(&Function::operator())
> { };
这本质上是一个转发特性,允许函子(具有 operator()
的对象)与这个特性类一起使用.它是从 operator()
的特征继承的主模板的定义.当后面定义的专业不匹配时会选择这个版本.
That is essentially a forwarding trait to allow functors (objects which have an operator()
) to be used with this traits class. It's a definition of the primary template which inherits from the traits for operator()
. This version will be selected when the specialization which is defined later is not matched.
template <
typename ClassType,
typename ReturnType,
typename... Arguments
>
struct function_traits<
ReturnType(ClassType::*)(Arguments...) const
>
这开始定义 function_traits
的部分特化,用于指向成员函数的指针.当您将成员函数指针类型作为模板参数传递给 function_traits
时,将选择此特化.返回类型、类类型和参数类型将被推导出为模板参数.
That begins the definition of a partial specialization of function_traits
for pointers to member functions. When you pass a member function pointer type as the template argument to function_traits
, this specialization will be selected. The return type, class type and argument types will be deduced as template parameters.
typedef ReturnType result_type;
这是一个简单的typedef
,它将推导出的ReturnType
模板参数别名为result_type
.
That is a simple typedef
which aliases the deduced ReturnType
template parameter to result_type
.
template <std::size_t Index>
using argument = typename std::tuple_element<
Index,
std::tuple<Arguments...>
>::type;
这就是所谓的别名模板.当您提供诸如 function_traits<myFunc>::template argument<2>
之类的索引时,它将折叠为 typename std::tuple_element<2, std::tuple<Arguments...>>::type
.这样做的目的是在索引 Index
处提取参数的类型.作者没有编写所有模板元编程代码来手动执行此操作,而是选择使用 std::tuple
中的现有代码.std::tuple_element
提取元组的 n 个元素的类型.
That is what is called an alias template. When you provide an index such as function_traits<myFunc>::template argument<2>
, it will collapse down to typename std::tuple_element<2, std::tuple<Arguments...>>::type
. The goal of that is to extract the type of the argument at index Index
. Rather than writing out all the template metaprogramming code to do that manually, the author chose to use the existing code in std::tuple
. std::tuple_element
extracts the type of the nth element of a tuple.
static const std::size_t arity = sizeof...(Arguments);
sizeof...
用于获取可变参数模板参数包的大小,因此这一行将函数的参数个数存储在静态整数成员 arity
.
sizeof...
is used to get the size of a variadic template parameter pack, so this line stores the number of arguments for the function in the static integral member arity
.
这篇关于了解函数特征模板的工作原理.特别是成员函数的指针是怎么处理的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!