If you have this function
template<typename T> f(T&);
And then try to call it with, let's s开发者_高级运维ay an rvalue like
f(1);
Why isn't T just be deduced to be const int, making the argument a const int& and thus bindable to an rvalue?
This is mentioned as a potential solution in the document I linked in the recent C++0x forwarding question.
It would work fairly well, but it breaks existing code. Consider (straight from the document):
template<class A1> void f(A1 & a1)
{
std::cout << 1 << std::endl;
}
void f(long const &)
{
std::cout << 2 << std::endl;
}
int main()
{
f(5); // prints 2 under the current rules, 1 after the change
int const n(5);
f(n); // 1 in both cases
}
Or
// helper function in a header
template<class T> void something(T & t) // #1
{
t.something();
}
// source
#include <vector>
void something(bool) // #2
{
}
int main()
{
std::vector<bool> v(5);
// resolves to #2 under the current rules, #1 after the change
something(v[0]);
}
This also fails to forward the value category (lvalue or rvalue), which isn't much of a problem in C++03. But since this fix could only be done during C++0x, we'd effectively shutting ourselves out from rvalue references when forwarding (a bad thing). We should strive for a better solution.
It is, but only if you declare f
to take T const &
.
template <typename T> void f(T &);
template <typename T> void g(T const &);
void x() { f(1); } // error: invalid initialization of non-const reference
void y() { g(1); } // no error
And if you declare both f(T &)
and f(T const &)
, it'll choose the const-qualified one:
template <typename T> void f(T &);
template <typename T> void f(T const &);
void x() { f(1); } // no error, calls f(T const &)
Now maybe you're saying “in the first example, why does it generate a temporary of type int
for the call to f
when it could have generated a temporary of type const int
and made the code compile?” The best answer I have for you is that that would be inconsistent with the overload resolution behavior when the argument isn't an integer constant.
精彩评论