MST
星途 面试题库

面试题:C++ 右值引用完美转发的复杂场景

假设有一个函数模板`template<typename... Args> void func(Args&&... args)`,它要将参数完美转发给另一个函数`void targetFunc(int, double, std::string)`。请写出`func`函数中正确转发参数的代码,并且解释在这个过程中`std::forward`是如何保证参数的右值或左值属性不被改变的。如果`targetFunc`有多个重载版本,如何确保`func`能够正确转发到合适的重载版本?
37.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
template<typename... Args> 
void func(Args&&... args) {
    // 使用std::apply将参数包展开并转发给targetFunc
    std::apply([](auto&&... a) { targetFunc(std::forward<decltype(a)>(a)...); }, std::make_tuple(std::forward<Args>(args)...));
}

std::forward保证参数属性不被改变的原理

  1. std::forward的作用std::forward是一个类型转换函数,它的主要目的是在模板函数中,根据实参的原始类型,将参数以正确的左值或右值形式转发出去。
  2. 模板参数推导:在func函数模板中,Args&&... args是一个转发引用(universal reference)。当调用func时,编译器会根据传入的实参类型来推导Args的类型。如果传入的是左值,Args会被推导为左值引用类型;如果传入的是右值,Args会被推导为非引用类型。
  3. std::forward的实现std::forward通过条件判断来决定如何转换参数。如果Args是左值引用类型,std::forward<Args>(arg)会将arg转换为左值;如果Args是非引用类型,std::forward<Args>(arg)会将arg转换为右值。这样就保证了参数在转发过程中其左值或右值属性不被改变。

确保func能够正确转发到合适的重载版本

  1. 重载决议规则:C++的重载决议机制会根据函数调用时实参的类型来选择最合适的重载版本。在func函数中,通过std::forward将参数以正确的类型转发给targetFunc,这样targetFunc的重载决议就会基于原始实参的类型来进行。
  2. 示例:如果targetFunc有多个重载版本,例如:
void targetFunc(int, double, std::string);
void targetFunc(int, double, int);

当调用func时,只要func中的参数转发使用了std::forward,编译器就会根据传入func的实参类型,正确地将调用转发到合适的targetFunc重载版本。例如:

func(1, 2.0, std::string("hello")); // 会转发到void targetFunc(int, double, std::string)
func(1, 2.0, 3); // 会转发到void targetFunc(int, double, int)

编译器会根据func调用时实参的类型,在targetFunc的多个重载版本中做出正确选择。