[英]C++ primer template universal reference and argument deduction
Hello I have this example from C++ primer:你好,我有这个来自 C++ 入门的例子:
template <typename T> void f(T&& x) // binds to nonconstant rvalues { std::cout << "f(T&&)\\n"; } template <typename T> void f(T const& x) // lvalues and constant revalues { std::cout << "f(T const&)\\n"; }
And here is my attempt to test the output:这是我测试输出的尝试:
int main(){
int i = 5;
int const ci = 10;
f(i); // f(T& &&) -> f(int&)
f(ci); // f(T const&) -> f(int const&)
f(5); // f(T &&) -> f(int&&)
f(std::move(ci)); // f(T&&) -> f(int const&&)
cout << '\n';
}
The output:输出:
f(T&&)
f(T const&)
f(T&&)
f(T&&)
In the book the version of f
taking a forwarding reference is said to bind only to non-constant rvalues but in main
I've passed a constant rvalue f(5)
and f(std::move(ci))
but still the first version called.在这本书中,采用转发引用的
f
版本据说只绑定到非常量右值,但在main
我已经传递了一个常数右值f(5)
和f(std::move(ci))
但仍然是第一个版本称为。
Is there a way to call the second version f(T const&)
passing an rvalue?有没有办法调用传递右值的第二个版本
f(T const&)
? I know I can do it explicitly: f<int const&>(5);
我知道我可以明确地做到这一点:
f<int const&>(5);
or f<int const&>( std::move(ci) );
或
f<int const&>( std::move(ci) );
but I want to know where can be called passing in an rvalue?但我想知道在哪里可以调用传递右值? Thank you!
谢谢!
I think the comment after the forwarding reference version of f
is not correct: f(T&&) // binds to nonconstant rvalues
because it can be bound to constant rvalues so for example:我认为
f
的转发参考版本之后的注释不正确: f(T&&) // binds to nonconstant rvalues
因为它可以绑定到常量右值,例如:
f(std::move(ci)); // f(int const&&) and not f(int const&)
The comments in the book are, evidently, not entirely correct.显然,书中的评论并不完全正确。 When you have the two overloads available of
当你有两个可用的重载时
template <typename T> void f(T&& x);
template <typename T> void f(T const& x);
both of them can always be called with any argument (with some exceptions that I'll omit here), but the second one will be preferred if the argument is a const
lvalue.它们总是可以用任何参数调用(有一些例外,我将在此处省略),但如果参数是
const
左值,则首选第二个。 The first one will be preferred under all other circumstances thanks to the reference collapsing rules that apply when deducing template arguments.由于在推导模板参数时适用的引用折叠规则,第一个在所有其他情况下将是首选。
However, let's say that T
is fixed by an enclosing class:但是,假设
T
由封闭类固定:
template <class T>
struct S {
void f(T&& x);
void f(T const& x);
};
and let's assume that T
is a non- const
object type.让我们假设
T
是一个非const
对象类型。 Now, the situation is different because T
is not deduced when calling f
.现在,情况有所不同,因为在调用
f
时不会推导出T
The comments in the book seem to be referring to this latter situation, where the first S::f
now may be called with non- const
rvalues of type T
but not with const
rvalues of type T
nor lvalues of (possibly const
) T
.书中的评论似乎指的是后一种情况,其中第一个
S::f
现在可以用T
类型的非const
右值调用,但不能用T
类型的const
右值调用,也不能用(可能是const
) T
左值调用。 The code, unfortunately, doesn't match up with the comments.不幸的是,代码与注释不匹配。
Let's go back to the actual code that's in the book.让我们回到书中的实际代码。 As I said, the function taking
T const&
will be preferred when the argument is a const
lvalue.正如我所说,当参数是一个
const
左值时,采用T const&
的函数将是首选。 Let's say that the argument is 5
, but you want to explicitly call the second function even though it would not normally be selected.假设参数是
5
,但您想显式调用第二个函数,即使它通常不会被选中。 There are a few ways to do this.有几种方法可以做到这一点。 The one that is easiest to read is to actually turn the argument into a
const
lvalue:最容易阅读的是将参数实际转换为
const
左值:
f((const int&)5);
Your suggestion of f<const int&>(5)
also works, but is a bit more confusing.您对
f<const int&>(5)
也有效,但有点令人困惑。 The reason why it is confusing is that it requires the reader of the code to actually do the reference collapsing mentally and then remember that the first overload is less specialized than the second one.之所以令人困惑,是因为它要求代码的读者在心理上实际进行引用折叠,然后记住第一个重载不如第二个重载专门化。 A third method is:
第三种方法是:
static_cast<void(*)(int const&)>(&f)(5);
Although this one is the hardest to read, the part before the (5)
can be used whenever one particular overload needs to be extracted and bound to a function pointer.尽管这一部分最难阅读,但只要需要提取一个特定的重载并将其绑定到函数指针,就可以使用
(5)
之前的部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.