我想编写一个函数,该函数将评估一些返回一对(可能作为引用,可能包含引用)并返回第二个元素的表达式,但它转发引用而不是复制它们。
这是一个不太有效的示例:
#include <utility>
#include <type_traits>
#include <iostream>
using namespace std;
template<typename F>
decltype(auto) foo(F&& func)
{
return get<1>(std::forward<F>(func)());
}
pair<int, int> value_of_values()
{
return make_pair(2, 3);
}
pair<int &, int &> value_of_refs()
{
static int x = 4;
static int y = 5;
return pair<int &, int &>(x, y);
}
pair<int, int> &ref_of_values()
{
static pair<int, int> p(6, 7);
return p;
}
int main()
{
cout << foo(value_of_values) << '\n';
cout << foo(value_of_refs) << '\n';
cout << foo(ref_of_values) << '\n';
return 0;
}
问题在于foo(value_of_values)
:value_of_values
返回一个纯右值,但get<1>
返回一个右值引用,因此 foo 返回一个对立即消失的临时的右值引用。
我知道我可能可以做一些模板元编程decltype
来区分函数返回值是包含非引用(必须作为非引用返回)的纯右值的情况与其他情况,但是有没有更优雅的解决方案?
(使用std::forward<F>(func)().second
而不是get<1>(...)
没有帮助:如果用括号括起来,则会出现完全相同的问题,因为对prvalue的成员访问是一个xvalue,导致decltype(auto)
推断int &&
,如果没有括号,则ref_of_values
案例返回副本而不是引用,因为无decltype
括号成员访问表达式的语义)。