The below code attempts to implement basic Decorator Design Pattern using references to refer to the base component class Paragraph
#include <string>
#include <iostream>
using std::cout; using std::endl; using std::string;
// component
class Paragraph{
public:
Paragraph(const string& text = "") : text_(text) {}
virtual string getHTML() const { return text_; }
private:
const string text_;
};
// first decorator
class BoldParagraph : public Paragraph {
public:
BoldParagraph(const Paragraph& wrapped): wrapped_(wrapped) {}
string getHTML() const override {
return "<b>" + wrapped_.getHTML() + "</b>";
}
private:
const Paragraph &wrapped_;
};
// second decorator
class ItalicParagraph : public Paragraph {
public:
ItalicParagraph(const Paragraph& wrapped): wrapped_(wrapped) {}
string getHTML() const override {
return "<i>" + wrapped_.getHTML() + "</i>";
}
private:
const Paragraph &wrapped_;
};
int main(){
Paragraph p("Hello, World!");
BoldParagraph bp(p); cout << bp.getHTML() << endl;
BoldParagraph bbp(bp); cout << bbp.getHTML() << endl;
ItalicParagraph ibp(bp); cout << ibp.getHTML() << endl;
}
When run, it produces
<b>Hello, World!</b>
<b>Hello, World!</b>
<i><b>Hello, World!</b></i>
rather than
<b>Hello, World!</b>
<b><b>Hello, World!</b></b>
<i><b>Hello, World!</b></i>
That is, the second wrapped function getHML() appears to be skipped if it is for the same subclass BoldParagraph for object bbp, but not if it is for different subclasses ItalicParagraph and BoldParagraph for object ibp. Similar code with pointers rather than references works as expected.
why is that?
The reason is that bbp(bp) with bp being of type BoldParagraph calls the (implicitly defined) copy constructor BoldParagraph::BoldParagraph(const BoldParagraph &)This then performs a member wise copy/assignment, such that wrapper_ gets sliced and will then be of type Paragraph & rather than BoldParagraph &. To overcome this, you'll have to provide an explicit copy constructor for BoldParagraph::BoldParagraph(const BoldParagraph &), which then calls your individual one:
BoldParagraph(const BoldParagraph& wrapped) : BoldParagraph((Paragraph&)wrapped) {} ;
The default copy constructor is being called. This creates a copy of your original object passed in (bp), rather than a wrapper around bp. You could fix by declaring your own copy constructor, but I don't recommend it:
BoldParagraph(const BoldParagraph &wrapped) : wrapped_(wrapped) {}
To clarify, the default copy constructor copies the values passed in object, like so:
BoldParagraph(const BoldParagraph &original) : wrapped_(original.wrapped_) {}
And, the more I think about it, the more I think my suggested fix is incorrect. There can/probably will be nasty side-effects. I would recommend fixing by making your constructors take pointers.
Answers here will show possible side-effects of having a copy constructor that does not perform a copy:
Copy Constructor in C++ is called when object is returned from a function?
A concrete example using a copy constructor that wraps instead of copies:
void AFunction(BoldParagraph bp)
{
cout << bp.getHTML() << endl;
}
int main() {
Paragraph p("Hello, World!");
BoldParagraph bp(p); cout << bp.getHTML() << endl;
BoldParagraph bbp(bp); cout << bbp.getHTML() << endl;
AFunction(bbp);
output:
<b>Hello, World!</b>
<b><b>Hello, World!</b></b>
<b><b><b>Hello, World!</b></b></b>
Oh, great, thank you much! That was hard to spot. I ended up adding this
BoldParagraph(const BoldParagraph& wrapped) :
BoldParagraph(static_cast<const Paragraph&>(wrapped)) {}
to make the code happy
Related
I have a class member which is of type std::function that binds to this pointer by using std::bind.
I implemented assignment operator which must also copy the callable object, however issue is in that, which this should be copied? this this or other this?
Here is sample compileable code to demonstrate:
#include <functional>
#include <iostream>
using func = std::function<void()>;
struct A
{
~A()
{
std::cout << "---destructor: " << this << std::endl;
other_callable();
this_callable();
}
A(const char* name) :
mName(name)
{
other_callable = std::bind(&A::f, this);
this_callable = std::bind(&A::f, this);
}
A& operator=(const A& ref)
{
if (this != &ref)
{
other_callable = ref.other_callable;
this_callable = std::bind(&A::f, this);
mName = ref.mName;
}
return *this;
}
void f()
{
std::cout << mName << ": " << this << std::endl;
}
func other_callable;
func this_callable;
const char* mName;
};
int main()
{
A a("a");
A b("b");
a.other_callable();
b.this_callable();
std::cout << "-------------------" << std::endl;
a = b;
}
Following is non unique sample output:
a: 00000090447FF3E0
b: 00000090447FF490
-------------------
---destructor: 00000090447FF490
b: 00000090447FF490
b: 00000090447FF490
---destructor: 00000090447FF3E0
b: 00000090447FF490
b: 00000090447FF3E0
As you can see non expected callable object is called in second instance.
What is the problem?
Problem is with this pointer that is stored inside the callable object, copying the callable also copies the this pointer which means this is no longer this but rather "other this".
To understand my issue, the callable object is an event callback that is being called from external code which assumes that callable will execute on this instance but it doesnt, it executes on other instance that was copied.
My question is what would be the correct way to implement copy semantics here?
Right now I favor the this_callable version rather than other_callable because it referrs to this this rather than other this.
But I'm not sure whether this is good or bad beyond that it works as expected, while simply copying the callable (other_callable) causes bugs in my code not easy to explain beyond this example.
Is my design with this_callable acceptable or should I use other_callable for copy sematics and change design elsewhere?
I am trying to understand how move semantics work in particular with the standard string. My primary concern is how to expose a string member variable of a class through a method, for example a getter.
So I made this example program.
#include <iostream>
#include <string>
using namespace std;
class Object {
string _s;
public:
Object(string s) : _s(s) {}
string get1() { return _s; }
string get2() { return move(_s); }
void print() { cout << "'" << _s << "'" << endl; }
};
int main() {
Object obj("0123456789ABCDEF_");
string s1 = obj.get1();
obj.print(); // prints '0123456789ABCDEF_'
string s2 = obj.get2();
obj.print(); // prints ''
}
Both methods get1() and get2() return by value.
I expected the get1() to automatically move the internal _s, however as you can see that is not the case. The get2() on the other hand makes the move, though this is expected as I explicitly ask for it.
So the question is why get1() does not move _s.
Phil1970 answered this in a comment above.
Move semantics work with rvalues. The _s member variable is apparently an lvalue and that is why get1() results in a copy instead of a move.
I'm trying to write a class that contains a function returning one of the class members, and I want to allow the caller to either move or copy the returned value. I wrote some dummy structs to test this; and after trying different variations, this seems to give me what I want.
#include <iostream>
using namespace std;
struct S {
int x;
S() : x(10) { cout << "ctor called\n"; }
S(const S& s) : x(s.x) { cout << "copy ctor called\n"; }
S(S&& s) : x(s.x) { cout << "move ctor called\n"; }
// I'm implementing move and copy the same way since x is an int.
// I just want to know which one gets called.
};
struct T {
S s;
T() : s() {}
S&& Test() && {
return move(s);
}
const S& Test() & {
return s;
}
};
int main() {
T t;
auto v = move(t).Test();
cout << v.x << "\n";
T t2;
auto w = t2.Test();
cout << w.x << "\n";
return 0;
}
The code prints out (with clang++-5.0 c++14):
ctor called
move ctor called
10
ctor called
copy ctor called
10
Is this an acceptable way to implement what I want? I have a few questions:
In the first Test function, I tried both S&& and S for the return type and it doesn't change the output. Does && mean anything for the (non-template) returned type?
Is it guaranteed that auto v = move(t).Test() would only invalidate the "moved" member? If struct T had other member variables, can I assume this call wouldn't invalidate them?
In the first Test function, I tried both S&& and S for the return type and it doesn't change the output. Does && mean anything for the (non-template) returned type?
There are little differences:
S&& is a (r-value) reference, so object is not yet moved.
returning S would move-construct S, so member is moved once the method is called.
For move(t).Test();, return ingS&& does nothing whereas returning S would move the member.
Is it guaranteed that auto v = move(t).Test() would only invalidate the "moved" member? If struct T had other member variables, can I assume this call wouldn't invalidate them?
Yes, only T::s is moved. std::move is just a cast to rvalue.
Yes it is acceptable way to implement this.
It does the same thing because returned value is temporary object, thus rvalue.
Depends on what you mean by invalidating
Can someone explain why the original object that is passed to a new object via std::move is still valid afterwards?
#include <iostream>
class Class
{
public:
explicit Class(const double& tt) : m_type(tt)
{
std::cout << "defaultish" << std::endl;
};
explicit Class(const Class& val) :
m_type(val.m_type)
{
std::cout << "copy" << std::endl;
};
explicit Class(Class&& val) :
m_type(val.m_type)
{
m_type = val.m_type;
std::cout << "move: " << m_type << std::endl;
};
void print()
{
std::cout << "print: " << m_type << std::endl;
}
void set(const double& tt)
{
m_type = tt;
}
private:
double m_type;
};
int main ()
{
Class cc(3.2);
Class c2(std::move(cc));
c2.print();
cc.set(4.0);
cc.print();
return 0;
}
It outputs the following:
defaultish
move: 3.2
print: 3.2
print: 4
I would expect the calls to cc.set() and cc.print() to fail...
UPDATE
Thanks to answers below, we've identified that 1) I wasn't moving anything in the move constructor, and 2) std::move() on an int or double doesn't do anything because it's more expensive to move these types than to simply copy. The new code below updates the class's private member variable to be of type std::string instead of a double, and properly calls std::move when setting this private member variable in the Class' move constructor, resulting in an output that shows how a std::move results in a valid but unspecified state
#include <iostream>
#include <string>
class Class
{
public:
explicit Class(const std::string& tt) : m_type(tt)
{
std::cout << "defaultish" << std::endl;
};
explicit Class(const Class& val) :
m_type(val.m_type)
{
std::cout << "copy" << std::endl;
};
explicit Class(Class&& val) : m_type(std::move(val.m_type))
{
std::cout << "move: " << m_type << std::endl;
};
void print()
{
std::cout << "print: " << m_type << std::endl;
}
void set(const std::string val )
{
m_type = val;
}
private:
std::string m_type;
};
int main ()
{
Class cc("3.2");
Class c2(std::move(cc));
c2.print( );
cc.print();
cc.set( "4.0" );
cc.print();
return 0;
}
And finally the output:
defaultish
move: 3.2
print: 3.2
print:
print: 4.0
Because the standard says so.
Moved-from objects have a valid but unspecified state. That means you can still use them, but you can't be sure what state they'll be in. They could look just as they did before the move, depending on what is the most efficient way to "move" data out of them. For example, "moving" from an int makes no sense (you'd have to do extra work to reset the original value!) so a "move" from an int is actually only ever going to be a copy. The same is true of a double.
Although in this case it's got more to do with the fact that you didn't actually move anything.
In the code example, std::move determines which constructor gets called. Nothing more. So c2(std::move(cc)) calls the move constructor for Class. The move constructor for Class doesn't do anything to its argument, so cc is unchanged, and it can be used just as it could have before the call to the move constructor.
All the talk in comments and answers about the state of an object that has been moved from is about the requirements on standard library types, which will be left in a "valid but unspecified state" (17.6.5.15, [lib.types.movedfrom]). What you do with your types is not affected by that.
EDIT: sigh. You edited the code and changed the question. Now that your class holds a std::string instead of a float things are different, and the std::string object in cc is, indeed, in a "valid but unspecified state".
For the program code below, I have to write the the same code inside the pair of member functions which receiving rvalue and lvalue references.
My aim is to use only one from the pair (e.g.; only use the rvalue accepting ones), and the others. I read the reference of std::forward, as far as I understood, it looks like it is for this purpose. But, when I delete the lvalue reference taking ones, I get the following compiler error.
'TestClass::TestClass(const TestClass &)': cannot convert argument 1 from 'std::wstring' to 'std::wstring &&'
How do I prevent this code duplication?
#include <iostream>
#include <string>
class TestClass
{
public:
TestClass(const std::wstring & Text)
: Text(Text)
{
std::wcout << L"LValue Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( std::wstring && Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Same code here...*/
}
TestClass(const TestClass & Another)
: Text(Another.Text)
{
std::wcout << L"Copy Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( TestClass && Another)
: Text(std::forward<std::wstring>(Another.Text))
{
std::wcout << L"Move Constructor : " << Text << std::endl;
/*Same code here...*/
}
private:
std::wstring Text;
};
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
std::wstring Argument(L"Testing Copy");
TestClass Class1Copy(Argument);
TestClass Class1Move(L"Testing Move");
TestClass Class2Copy(Class1Copy);
TestClass Class2Move(std::move(Class1Move));
_wsystem(L"pause");
return 0;
}
Output:
LValue Constructor : Testing Copy
RValue Constructor : Testing Move
Copy Constructor : Testing Copy
Move Constructor : Testing Move
Press any key to continue . . .
If move construction is expected to be extremely cheap, you can take by value and move-from the value. This does exactly 1 more move than a pair of copy and move overloads.
If you want optimal efficiency, and/or if move construction is cheaper but not cheap enough to neglect, you can forward:
template<class T>
std::decay_t<T> copy(T&& t) {
return std::forward<T>(t);
}
class TestClass {
public:
TestClass(std::wstring const& Text)
TestClass( copy(Text) )
{}
TestClass(TestClass const& o)
: TestClass( o.Text )
{}
TestClass(TestClass&& o)
: TestClass( std::move(o).Text ) // pattern does the right thing more often than `std::move(o.Text)` does.
{}
// only "real" ctor:
TestClass( std::wstring&& Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Code here...*/
}
// ...
now everything forwards down to the one constructor.
You can even mix the two techniques: use by-value for std::wstring (as we know that is cheap-to-move) and do forwarding stuff for the TestClass code (or anything less likely to be stable).
You can take by value and then move. Then you only need N overloads, not 2N:
TestClass(std::wstring Text)
: Text(std::move(Text))
{
}
You can avoid the copy constructor and move constructor duplication by writing nothing at all; the compiler will generate them by default in this case.
I don't think you can do that since the function's signatures determine when and where they are used. It's like a copy constructor and an assignment operator. They do somewhat similar things but the compiler calls the appropriate one basee on context.
If you want to avoid reusing code, just factor out the commonality into a separate function.