面试题答案
一键面试- 实现函数模板:
#include <iostream>
#include <type_traits>
// 辅助函数模板,用于处理单个参数
template<typename T>
auto handleSingleArg(T arg) {
if constexpr (std::is_arithmetic_v<T>) {
return arg;
} else {
// 对于非数值类型的默认操作,这里简单返回0
return 0;
}
}
// 可变参数模板函数,用于累加所有参数
template<typename... Args>
auto sumArgs(Args... args) {
// 使用折叠表达式对参数包进行展开并累加
return (handleSingleArg(args) + ... + 0);
}
- 类型参数包展开:
- 在C++11及以上,我们使用折叠表达式
(handleSingleArg(args) + ... + 0)
来展开参数包Args...
。这里的...
是折叠表达式的关键符号,它会将参数包中的每个参数args
依次传递给handleSingleArg
函数,并通过+
运算符进行累加。累加的初始值为0
。在编译期,编译器会根据参数包的大小展开这个表达式,例如,如果有三个参数a, b, c
,则展开后的表达式类似handleSingleArg(a) + handleSingleArg(b) + handleSingleArg(c) + 0
。
- 在C++11及以上,我们使用折叠表达式
- 针对不同类型参数进行不同操作:
- 我们使用了
if constexpr
语句(C++17特性)在编译期根据类型进行不同操作。在handleSingleArg
函数模板中,std::is_arithmetic_v<T>
用于判断类型T
是否为算术类型(如整数、浮点数等)。如果是算术类型,就直接返回参数本身;如果是非算术类型,就返回一个默认值0
。这种方式允许我们在编译期根据类型做出不同的行为,而不需要运行时开销。
- 我们使用了
- 类型参数的模板实参推断规则:
- 在调用
sumArgs
函数时,编译器会根据传入的实际参数类型来推断模板参数Args
。例如,如果调用sumArgs(1, 2.5, 'a')
,编译器会推断出Args
为int, double, char
。编译器会根据实参的类型依次匹配模板参数包中的类型。对于每个实参,编译器尝试找到一个模板参数与之匹配,如果匹配成功,就确定了模板参数的类型。这里不需要显式指定模板参数,编译器会自动完成推断过程,使得代码编写更加简洁和通用。
- 在调用
你可以通过以下方式测试这个函数:
int main() {
auto result = sumArgs(1, 2.5, 'a');
std::cout << "Sum: " << result << std::endl;
return 0;
}