I am using c++11 currently and I am working on a friend function to print out sth, but before calling the print function I need to call a member function inside the class to access and serialize the two data member. I am having a problem modifying the ostream object.
The code is as below:
friend ostream& operator<<(ostream& os, const Card& c) {
c.serialize(os);
return os;}
void NumberCard:: serialize(ostream& os) const
{
Color c=this->getColor();
switch(c){
case Color::red: os=(os<<"R"<<this->getPoint());break;
case Color::yellow: os=(os<<"Y"<<this->getPoint());break;
case Color::blue: os=(os<<"B"<<this->getPoint());break;
case Color::green: os=(os<<"G"<<this->getPoint());break;
default:break;}}
My current method doesn't work and the error is:
use of deleted function 'std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator=(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'
It would be really appreciated if someone could give me some suggestions.
Don't use
os=(os<<"R"<<this->getPoint());
That is a problem since assignment to an ostream object is not supported by the standard library.
Use
os << "R" << this->getPoint();
ostream& os is a reference to an ostream. A C++ reference to an object is supposed to be indistinguishable from the actual object in terms of how it is used. This means that a reference cannot be reassigned -- rather, the object being referenced gets assigned to instead of the reference variable itself.
ostream is declared with a deleted copy-assignment operator, because you cannot copy a stream (this makes sense).
Combining these together, you'll understand that os = ... is causing the assignment operator to be called, which results in that error.
As it turns out, there's no need to reassign to os, since the reference returned by << is to the same (mutated) ostream object in the first place (this is done so that << calls can be chained).
Your switch code then simplifies to:
case Color::red: os << "R" << this->getPoint(); break;
case Color::yellow: os << "Y" << this->getPoint(); break;
// ...
Related
in C++, if a method is accepting left reference + pointer only,
it seems it suffices if we only have a template method with T& as its parameter, why we usually overload with test(T* ) as well ?
proof of concept: left reference method can take pointer argument.
#include <iostream>
using namespace std;
template<class T>
void test(T& arg) {
T value = arg;
cout << *value << endl;
}
int main() {
int b = 4;
int* a = &b;
test(a); // compiles and runs without issue.
return 0;
}
Why [do] we usually overload with test(T* ) as well?
I am not sure that we usually do anything of the sort, but if one were to overload for a pointer, it would be because pointers behave differently than object types. Remember, a pointer in fact is not an object but an address to an object.
The reason that test(a) compiles and runs without issue is because it is accepting a reference to a pointer to an object as its parameter. Thus, when the line cout << *value << endl; executes, the pointer is dereferenced back to an object and we see 4 printed to standard out.
As #HolyBlackCat mentioned, we usually want do different things for T& and T*.
As indicated in the example, for test(T&) we usually need to manually do dereference, this would result in the difference in the behavior, so it makes sense to have a overload like this.
I was wondering if there is a way to access a data member within a struct that is being pointed to by a void*? What I'm trying to explain will hopefully be more apparent in my example code:
int main()
{
struct S
{
int val;
};
S s;
s.val = 5;
void* p;
p = malloc(sizeof(S));
*(struct S*) p = s;
std::cout<< *(struct S*)p.val << std::endl;
}
I have ran this exact code casting p as *(int*)p and it printed fine, however, using exact code above results in a compilation error. Haven't been able to find an example that quite accomplishes this task. Is it possible to access the data members of the struct after it is casted? why or why not? if so, how?
The . operator has higher precedence than a C-style cast. So *(struct S*)p.val is treated as *((struct S*)(p.val)), which doesn't make sense since p is a pointer and does not have members.
So you need parentheses to specify what you intended:
std::cout<< (*(struct S*)p).val << std::endl;
Or equivalently,
std::cout<< static_cast<S*>(p)->val << std::endl;
[But also: the statement *(struct S*) p = s; technically has undefined behavior, even though all most implementations will allow it. This is because C++ has rules about when an object is created, and there was no object of type S previously at that address, and assignment does not create an object except for some cases involving union members. A similar statement that does not have this problem would be new(p) S{s};.
Also also: use of malloc or void* is usually not a good idea in C++ in the first place. malloc should only be used when interfacing with a C library that requires it. Anything for which void* seems useful can probably be done more safely using templates. In a few cases a void* might be the only way to do something or "cleverly" avoid code duplication or something, but still use it sparingly and always with extreme caution.]
Today I found that this code doesn't work as I expect it to work.
According to my knowledg for L-values copy constructor should be called while for R-values it should choose move constructor. Otherwise what's the purpose of std::move which actually does nothing but casts to R-value. I was expecting that return obj will call copy constructor, but it calls move.
I understand that copy is useless here, but that's about rules. What if my copy constructor has a side effect and that's my case (I know that it shouldn't, but technically it can - for example here: std::cout call).
Is there anything in standard that allows such behavior? Also how can I force a copy?
#include <iostream>
class X
{
public:
X() = default;
X(const X& r): i(r.i)
{
std::cout << "copy ctor" << std::endl;
}
X(const X&& r): i(r.i)
{
std::cout << "move ctor" << std::endl;
}
int i = 0;
};
X foo()
{
X obj;
obj.i = 10;
return obj;
}
int main()
{
X x = foo();
}
move ctor
move ctor
From cppreference (emphasis mine):
If [the returned expression] is an lvalue expression and the conditions for copy elision are met, or would be met, except that [the returned expression] names a function parameter, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if [the returned expression] were an rvalue expression (thus it may select the move constructor or a copy constructor taking reference to const), and if no suitable conversion is available, overload resolution is performed the second time, with lvalue [returned expression] (so it may select the copy constructor taking a reference to non-const).
The above rule applies even if the function return type is different from the type of [the returned expression] (copy elision requires same type)
Long story short, return implicitly tries to move what you return when it makes sense. It will only copy as a last resort (no move constructor available, for example).
#include <bits/stdc++.h>
int main () {
std::string foo = "string_1";
std::string bar = "string_2";
std::vector<std::string> myvector;
myvector.push_back (foo);
myvector.push_back (std::move(bar));
for (std::string x:myvector)
std::cout << x << '\n' ;
}
How's that code is diffrent when I exchange
for (std::string x:myvector)
for?
for (std::string& x:myvector)
I'm guessing there are a lot of places when I could find that, but I don't know what's the name of this measure, so I don't know what I should search for. Link to explanation will be enough if it's it's easier for you.
EDIT:
What's the diffrence between:
for(auto x:my_vector)
for(auto& x:my_vector)
for(auto&& x:my_vector)
What does '&' after class name mean?
The ampersand is part of the type in the declaration and signifies that the type is a reference. Reference is a form of indirection, similar to a pointer.
What's the diffrence between:
for(auto x:my_vector)
The loop variable is a non-reference. It will contain a copy of the object in the container.
for(auto& x:my_vector)
The loop variable is an lvalue reference. Since the variable references the objects in the container, they can be modified through that reference. This also avoids copying the objects, which may be advantageous if the copy is expensive.
for(auto&& x:my_vector)
The loop variable is a universal reference. This means that it will be either an lvalue or rvalue reference, depending on the type returned when the iterator of the container is dereferenced. As far as I know, there are only a few obscure cases where this is useful. You'll probably never need it.
I am trying to learn rvalue references, as an exercise I tried to do answer the following.
Is it possible to write a function that can tell (at least at runtime, better if at compile time) if the passed value is a value (non reference), a rvalue or an lvalue? for a generic type? I want to extract as much information about the type as possible.
An alternative statement of the problem could be:
Can I have a typeid-like function that can tell as much as possible about the calling expression?, for example (and ideally) if the type is T, T&, T const&, or T&&.
Currently, for example, typeid drops some information about the type and one can do better (as in the example the const and non-const reference are distiguished). But how much better than typeid can one possibly do?
This is my best attempt so far. It can't distinguish between a rvalue and a "constant". First and second case in the example).
Maybe distiguishing case 1 and 2 is not possible in any circumstance? since both are ultimately rvalue? the the question is Even if both are rvalues can the two cases trigger different behavior?
In any case, it seems I overcomplicated the solution as I needed to resort to rvalue conditional casts, and ended up with this nasty code and not even 100% there.
#include<iostream>
#include<typeinfo>
template<class T>
void qualified_generic(T&& t){
std::clog << __PRETTY_FUNCTION__ << std::endl;
std::clog
<< typeid(t).name() // ok, it drops any qualification
<< (std::is_const<typename std::remove_reference<decltype(std::forward<T>(t))>::type>::value?" const":"") // seems to detect constness rigth
<< (std::is_lvalue_reference<decltype(std::forward<T>(t))>::value?"&":"")
<< (std::is_rvalue_reference<decltype(std::forward<T>(t))>::value?"&&":"") // cannot distiguish between passing a constant and an rvalue expression
<< std::endl
;
}
using namespace std;
int main(){
int a = 5;
int const b = 5;
qualified_generic(5); // prints "int&&", would plain "int" be more appropriate?
qualified_generic(a+1); // prints "int&&" ok
qualified_generic(a); // print "int&", ok
qualified_generic(b); // print "int const&", ok
}
Maybe the ultimate solution to distiguish between the cases will involve detecting a constexpr.
UPDATE: I found this talk by Scott Meyers where he claims that "The Standard sometimes requires typeid to give the 'wrong' answer". http://vimeo.com/97344493 about minute 44. I wonder if this is one of the cases.
UPDATE 2015: I revisited the problem using Boost TypeIndex and the result is still the same. For example using:
template<class T>
std::string qualified_generic(T&& t){
return boost::typeindex::type_id_with_cvr<decltype(t)>().pretty_name();
// or return boost::typeindex::type_id_with_cvr<T>().pretty_name();
// or return boost::typeindex::type_id_with_cvr<T&&>().pretty_name();
// or return boost::typeindex::type_id_with_cvr<T&>().pretty_name();
}
Still it is not possible to distinguish the type of 5 and a+1 in the above example.