我有以下代码:
#include <iostream>
struct C {
int a;
int& get() { return a; }
};
struct D {
int a;
int get() { return a; }
};
template <typename T>
auto foo(T o) { // no sample code is complete without a foo
return o.get();
}
int main()
{
C c;
D d;
c.a = 2;
d.a = 42; // no sample code is complete without a 42
std::cout << "c=" << c.a << ", d=" << d.a << "\n";
c.get() = 3;
//d.get() = 43;
std::cout << "c=" << c.a << ", d=" << d.a << "\n";
foo(c) = 4; // <--- why won't this work?
//foo(d) = 44;
std::cout << "c=" << c.a << ", d=" << d.a << "\n";
}
为什么标记为行的行不能编译?看来编译器在推导foo<C>
的返回类型为int
而不是我期望的int&
。为什么会这样呢?我又该如何推断出参考呢?
答案 0 :(得分:6)
给出auto
,它被声明为非引用,因此我们要处理按值传递的情况。 auto
遵循template argument deduction的规则; int&
的引用部分将被忽略,则推导的类型为int
。
您可以改用decltype(auto)
(从C ++ 14开始)。
类型是
decltype(e)
,其中e
是初始化程序。
template <typename T>
decltype(auto) foo(T&& o) { // no sample code is complete without a foo
return o.get();
}
返回类型推导为decltype(o.get())
,并根据decltype
的规则,
如果表达式的值类别为lvalue,则decltype产生
T&
;
c.get()
返回int&
,它是一个左值,然后我们得到int&
的返回类型int
的代言人。
顺便说一句:请注意,如果o
仍按值传递,则返回的引用将被悬挂。