This question already has answers here:
Passing rvalue references between functions
(1 answer)
Rvalue Reference is Treated as an Lvalue?
(4 answers)
Closed 8 months ago.
void test(Foo&& a)
{
cout << "rvalue parameter" << endl;
}
void test(const Foo& a)
{
cout << "lvalue parameter" << endl;
}
it is my test program.
int main()
{
Foo&& a = Foo();
test(a);
return 0;
}
the result is that it will call the function test(const Foo& a).
why a will be regard as Foo& and compiler choose the second funtion.
Related
This question already has answers here:
Why do const references extend the lifetime of rvalues?
(2 answers)
Why doesn't a const reference extend the life of a temporary object passed via a function?
(4 answers)
Closed 13 days ago.
Someone asked this code in a Chinese QA forum
const string &a = "abcdefg";
cout << a << endl;
At first I thought it's illegal. Even if it can compile, it would crush when to use a, because what its reference was destructed. Until I tried my code:
class A
{
public:
A();
A(int a);
A(const string& name, int _a);
A(const A& o);
A(A&& o) noexcept;
A(std::initializer_list<A>);
virtual ~A();
A& operator=(const A& o);
A& operator=(A&& o);
int GetValue() const;
};
void test()
{
const A& a = 123;
cout << a.GetValue() << endl;
}
[![enter image description here][1]][1]
The destructor happens after calling a.GetValue(). How do I explain this?
[1]: https://i.stack.imgur.com/8qIUQ.png
This question already has answers here:
How come a non-const reference cannot bind to a temporary object?
(11 answers)
Error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
(2 answers)
cannot bind non-const lvalue reference of type to an rvalue of type
(1 answer)
Closed 3 months ago.
I try to overload operator << and ++ (post and pre).
This is part of my code, but I get error "e0349: no operator matches these operands".
Could you tell me where I made a mistake?
(C++, VS2022)
#include <iostream>
#include <string>
using namespace std;
class K {
int x, y;
public:
K(int a, int b) :x(a), y(b) {};
K() :x(0), y(0) {};
K operator++(int);
K& operator++();
friend ostream& operator<< (ostream & str, K & obj);
};
K K::operator++(int) {
K temp(*this);
x += 1;
y += 1;
return temp;
}
K& K::operator++() {
x += 1;
y += 1;
return *this;
}
ostream& operator<<(ostream& str, K& obj) {
str << "[" << obj.x << ", " << obj.y << "]";
return str;
}
int main(int argc, char* argv[])
{
K obj{10, 20};
cout << obj++ << endl; //here I get error
cout << obj << endl;
cout << ++obj << endl;
}
Simply the post-operator++ is written so that it returns a copy of the temporary value which can be used as rvalue but being that the signature of the insertion operator requires a reference of the value, it does not know how to retrieve the data passed as a copy. This is how you should modify the overloading function of the extract operator:
ostream& operator<<(ostream& str, K const& obj) {
str << "[" << obj.x << ", " << obj.y << "]";
return str;
}
You're simply telling the function that the passed value will have a constant reference that it won't change over time. So it is as if you are taking the reference of the copy value. I know it's very tricky as a thing but I should have cleared your minds enough
This question already has answers here:
How to properly overload the << operator for an ostream?
(6 answers)
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 2 years ago.
string var = "Hello";
cout << var << endl;
We get the result using only the object, without the help of a member variable. I want to implement a class that will work like string. For example:
class Test {
public:
int x = 3;
};
Test var2;
cout << var2 << endl;
How can I get implement the class so the cout line prints the value of x without referring to it?
The std::string class has operator << overloaded, that's why when you write:
std::string text = "hello!";
std::cout << var1 << std::endl; // calling std::string's overloaded operator <<
Prints the text held by it simply.
Thus, you need to overload the << operator for the class:
class Test {
int x = 3;
public:
friend std::ostream& operator<<(std::ostream& out, const Test& t) {
out << t.x;
return out;
}
}
// ...
Test var2;
std::cout << var2 << std::endl;
The ff() function returns a rvalue but when I change the return value of function to be const, does it return lvalue? Why does the following output change its output from "lvalue reference" to "rvalue reference" when I change test ff() { } into const test ff() { }
#include <iostream>
using namespace std;
class test { };
void fun( const test& a)
{
cout << "lvalue reference"<<endl;
}
void fun( test&& a)
{
cout << "rvalue reference"<<endl;
}
const test ff() { } // <<---return value is const now
int main()
{
fun(ff());
}
Output:
lvalue reference
void fun( test&& a) is a function that takes a reference to a non-const rvalue. ff returns a const test which is a const rvalue. You cannot bind a reference to a non-const rvalue to a const rvalue as that would violate const-correctness. This is why it instead binds to void fun( const test& a), which takes a reference to a const test
Do note that when returning by value there is no benefit to return a const thing over a thing. The only time adding const to the return type matters is when returning by reference. If you have a member function that is marked as const or returning a reference to a constant data member then you must use const to preserve const-correctness.
Your test function output is misleading and test functions should be instead:
void fun( const test& a)
{
cout << "lvalue const reference"<<endl;
}
void fun( test& a)
{
cout << "lvalue reference"<<endl;
}
void fun( test&& a)
{
cout << "rvalue reference"<<endl;
}
void fun( const test&& a)
{
cout << "rvalue const reference"<<endl;
}
then you will see what is really happening there.
In a case like this where you're interested in why the compiler chose one overload instead of another, it's often easiest to (more or less) ask the compiler directly how/why it made the decision it did, by only allowing it to select the other function, and seeing what error message it gives (or whether it may give no error message at all). In this case, we can remove the function taking a const lvalue reference to get code like this:
#include <iostream>
using namespace std;
class test { };
// void fun( const test& a)
// {
// cout << "lvalue reference"<<endl;
// }
void fun( test&& a)
{
cout << "rvalue reference"<<endl;
}
const test ff() { } // <<---return value is const now
int main()
{
fun(ff());
}
Now if we try to compile, the compiler will directly tell us why the remaining function wasn't selected:
trash9.cpp:16:3: error: no matching function for call to 'fun'
fun(ff());
^~~
trash9.cpp:8:6: note: candidate function not viable: 1st argument ('const test') would lose const qualifier
void fun( test&& a)
^
That's not as authoritative as a direct quote from the standard, but compilers are good enough at things like this that the error messages can be fairly informative.
This question already has answers here:
Overload resolution failure when streaming object via implicit conversion to string
(5 answers)
Closed 4 years ago.
I have a struct that works as a wrapper for other types as follows:
template<typename T>
struct A {
A& operator=(const T& value){
m_value = value;
return *this;
}
operator T() const {
return m_value;
}
private:
T m_value;
};
I use it like this:
int main() {
A<int> a;
a = 5; // Copy assignment constructor
std::cout << a << "\n"; // Implicit conversion to int
}
which works as expected. My problem occurs when using non-fundamental types as the following example shows:
int main() {
A<std::complex<int>> c;
c = std::complex<int>(2, 2);
std::cout << c << "\n";
}
The snippet above raises an invalid operands to binary expression error.
Why does this error occur? Why isn't the overloaded operator << of std::complex<int> used with the implicitly converted A<std::complex<int>>?
The stream operators for std::complex are template functions. They will not be invoked unless you actual have a std::complex as no conversions happens in template argument deduction. This means the compiler will not find a suitable overload to print a A<std::complex<int>>
You're first case for works because std::basic_ostream::operator << is overloaded to take an int and you are allowed one user defined conversion is overload resolution.
As a work arround you can define your own operator << that takes your wrapper and forward to the underlying types' operator <<. That would look like
template<typename T>
std::ostream& operator <<(std::ostream& os, const A<T>& a)
{
return os << static_cast<T>(a);
}