Notify the instance of the object when it is copied - c++

I have a class with lazy initialization. For the sake of simplicity let's say that it is a database proxy. An object of the class can be in any of two states: Ready and Initialized. Initially, when you construct the object, you specify the database address, and the object becomes Ready, but doesn't connect to the DB yet. When you call any function which wants to access the DB the object performs the connection and changes its state to Initialized. I want the object to initialize when I do anything with it.
Including, I want to make this object copyable. However, I don't want to allow the uninitialized object to be copied: in this case two connections will be performed later. Instead I would like to notify the object when I'm trying to copy it so it can perform initialization, switch the state and only then copy to another object.
Here is a sample code with the behavior I'm trying to achieve.
class Foo {
public:
Foo(Config conf) :
initialized(false)
{
// process the config somehow
}
void tryInitialize() {
if (!initialized) {
// perform the connection
initialized = true;
connection = createConnection();
}
}
void accessDatabase() {
tryInitialize();
// do something
}
Foo(const Foo& other) {
other.tryInitialize(); // this is a problem because other is const
initialized = true;
connection = other.connection;
}
private:
bool initialized;
DBConnection connection;
};
The problem still arises if I declare copy ctor as Foo(Foo other) because in this case the original object wouldn't be modified as well. Of course, this is achievable with move ctor, but I'd like to use copy ctor as well.
P.S. The real problem is not much about databases but complex enough to be explained here. So you can assume that no real world problems about databases matter here: connection attempts always succeed, having two instances of the same connection is OK, etc.

You can mark your private members as mutable and make you tryInitialize() method const (or you can write some other private initialize method with constness).
This solution is a bit dirty but anyway it solves your problem :)

If i'm understanding this correctly, you want a copy constructor that can modify the passed in argument. If this is true then what your are saying is correct, foo( foo other ) would not work because that would only pass a copy of the argument, and foo( const foo& other ) would not be modifiable in the copy constructor. The solution is simply passing by reference.
Foo(Foo& other) {
initialized = true;
other.tryInitialize(); // Now will be able to modify other
connection = other.connection;
}
Reference article below for const correctness of copy constructors below, and I quote, " Pass by non-const reference ONLY if the function will modify the parameter and it is the intent to change the caller's copy of the data, otherwise pass by const reference."
http://www.cplusplus.com/articles/y8hv0pDG/
Reference article for mutable below, "mutable - applies to non-static class members of non-reference non-const type and specifies that the member does not affect the externally visible state of the class (as often used for mutexes, memo caches, lazy evaluation, and access instrumentation). mutable members of const classes are modifiable. (Note: the C++ language grammar treats mutable as a storage-class-specifier, but it does not affect storage class.)"
http://en.cppreference.com/w/cpp/language/cv
See example of using mutable from "Effective C++ Third Edition" by Scott Meyers, and apply for alternative solution to pass by reference.
class CTextBlock {
public:
...
std::size_t length() const;
private:
char *pText;
mutable std::size_t textLength;
mutable bool lengthIsValid;
};
std::size_t CTextBlock::length() const
{
if(!lengthIsValid) {
textLength = std::strlen(pText);
lengthIsValid = true;
}
return textLength;
}

Related

Is there any way to correctly std::move const data?

My problem is that I have to choose between copying const data, and moving non-const data, and I conceptually do not see a reason why, in my situation, it wouldn't be safe to move const data to a const destination. I am also aware that moving from a const object is illogical - so perhaps there's some other way to achieve what I am attempting to do...
I have a Builder class that sets up a BigData object that I don't want to have to copy around. Once the builder is finished it 'emits' the data as const, because it shouldn't be modified after that point. The builder is temporary, and can then be discarded, but the data should live on, as a const member in a wrapper class that can interrogate it. The builder is a generic type (doesn't know about the details of the data), while the wrapper is specific to the contents of the data. This is achieved via type-erasure within the data, but that's not relevant to this question, except to make it clear that it isn't desirable to merge the builder and wrapper.
The below code describes the above, and does not compile unless you remove BigData's move constructor. The compile error shows that this code would copy the data, which is undesirable:
prog.cpp:26:57: error: use of deleted function ‘constexpr BigData::BigData(const BigData&)’
Wrapper( const BigData&& In ) : Data( std::move(In) ) {}
^
class BigData
{
// Only a builder can create data
friend class Builder;
BigData() = default;
public:
// Move only
BigData( BigData&& ) = default;
};
class Builder
{
BigData Data;
public:
const BigData&& Build() & { return std::move(Data); }
// Functions to set up data go here
};
class Wrapper
{
const BigData Data;
public:
Wrapper( const BigData&& In ) : Data( std::move(In) ) {}
// Functions to query data go here
};
std::unique_ptr<Wrapper> DoBuild()
{
Builder b;
// call functions on b to set up data here
return std::make_unique<Wrapper>( b.Build() );
}
The above code can also be found at https://ideone.com/tFkVEd.
The problem can be fixed by changing all const BigData&& into just BigData&& but I don't want the data to be changeable after it is retrieved from Build().
Finally, the problem could also be solved by returning the data from Build in a unique_ptr<const BigData>, and have the Wrapper take ownership of this, but my problem with this is that a pointer can be null, so all usage of Data within Wrapper would have to first check that the Data pointer is valid. This is why I want to move the const data into the wrapper via an rvalue reference, and also why the wrapper must be constructed with the data.
Is there any way to achieve what I want, or have I come up against a limitation of c++?
Many thanks in advance for your input.
NB: Related questions that I have encountered while trying to solve this myself:
Why can we use `std::move` on a `const` object?
Return value or rvalue reference?
Is returning by rvalue reference more efficient?
There is no way to std::move a const T as it would mutate the given object. (Unless you make the members mutable and make a T(const T&&) constructor to do the move, which I would not recommend).
A better solution in my opinion would be to make all the mutating functions private, such that only the builder can access them, and return a T&&.
firstly, to move an object, exactly means to modify it.
secondly, I don't think you should prevent all the modifications to BigData. trying to return a BigData const&& and prevent it to be modified, is just like trying to prevent it to be const_cast-ed, which is a wasted effort. in this case, you can just declare that to modify a BigData inside a Builder is definitely an undefined behavior, except to move it and then return a BigData&&.
thirdly, if you want it not to be modified exactly (except to be moved), you should consider if to construct a Wrapper is the only usage for Builder. if so, why not provide a constructer Wrapper(Build&) to do that? it can prevent all potential modifications from Builder to Wrapper.
finally, to answer the question how to move a const BigData object, I suggest BigData(BigData const&&) and const_cast, which means you allow all const BigData to be moved as if it was non-const.

How to have const members in stl container values in C++?

I like to make my C++ member variables const if they should not be changed once the object is constructed, however, sometimes they need to be modified by STL. For example, if I have a vector of my class with const members and I try to swap two elements in the vector, STL tries to use the default generated operator=() and fails because of the const member variables.
I feel like the operator=() is like a constructor in that the whole object is being created and thus would like some way to allow operator=() while still having my const member variables.
Is there anyway to do this in C++03? If not, what about in C++11, perhaps in-place construction is for this?
class Foo {
const int _id;
static int _generate_unique_id();
public:
Foo()
: _id(_generate_unique_id()) {
}
};
vector<Foo> foo_vector;
// Fill foo_vector with several entries:
// [...]
// Try to swap the first and second elements of the vector:
swap(*foo_vector.begin(), *(foo_vector.begin() + 1));
// The above fails to compile due to const member variable _id
// prohibits us from using the default assignment operator.
A solution for storing not assignable objects in standard library containers is storing (smart) pointers to the objects. Not always ideal, but workable.
For example, if I have a vector of my class with const members and I try to swap two elements in the vector, STL tries to use the default generated operator=() and fails because of the const member variables.
Implement the "big three and a half" (default and copy constructor, assignment operator and swap), with the assignment operator explicitly skipping the reassignment if _id.
What you want is a thing like the Java immutable idiom.
This is awesome with pointers (and thus, garbage collected languages) and less awesome with value-semantic languages like C++.
You have two solutions:
1 - Make your object immutable in the interface
The member is private (or it should be), so no one but the class itself (and its friends) can modify it. So all you need is to make sure no one does inside the class (which you control) and offer no way in the protected/public interface to leave others the power to do so.
TL;DR: Make your object non const. Don't modify it inside the class. Add a const getter. Remove the setter (if any).
2 - Use a std::unique_ptr<const Data>
Now we follow the Java idiom. The object is const, but the pointer can be reattributed, which is exactly what you want.
This is actually better than the const Data * member alternative because of its exception safety.
Bonus: Don't manually call the destructor to reconstruct again the object
There's an answer proposing that.
As mentionned first by sehe, don't do that.
Your point is to increase the quality of your code, which means your code will need to be exception safe, at one point or the other. And manually playing with your object lifetime will make it unusable in quality code.
Read Herb Sutter's article on the subject: http://www.gotw.ca/gotw/023.htm
const on members doesn't just prevent the programmer from modifying the value of the member during its lifetime; it also enables compiler optimisations by specifying that attempts to modify it are undefined behaviour (see const member and assignment operator. How to avoid the undefined behavior?).
One way to do what you want is to write a nonmodifiable container that gives semantic const while leaving you as the programmer the possibility of modifying the contained value:
template<typename T> class nonmodifiable {
T t;
public:
nonmodifiable(T t): t{std::move(t)} {}
operator const T &() const { return t; }
nonmodifiable &operator=(const nonmodifiable &) = delete;
};
You can now write:
class Foo {
nonmodifiable<int> _id;
// etc.
};
and because neither _id nor its contained value are const, use the destruct-placement new dance to reassign its value:
Foo &operator=(const Foo &foo) {
if (this != &foo) {
_id.~nonmodifiable<int>();
new (&_id) nonmodifiable<int>(foo._id);
}
return this;
}

is it possible to restrict class instances to be used only as temporaries?

is it possible to restrict class instances to be used only as rvalues (e.g. temporaries)?
for example, I have class Wrapper whose constructor takes A const& and saves this reference in its member. It's a dangerous because lifetime of Wrapper instance cannot be longer than lifetime of A instance, but it's fine if Wrapper is temporary.
I think that even wanting to do this is a sign of a really bad design.
However, you could make all constructors private and make a friend function that returns an rvalue. That should do the trick.
I don't think it would be safe:
const A &a = YourClass( tmp );
YourClass in this case is the class you're looking for which only allow temporary instances, tmp is the temporary value you pass to the constructor.
It's possible (ie: safe, defined behavior) to have a constant reference to a temporary (ie: a), but the temporary itself (such instance of YourClass) has got a reference to tmp which is no longer valid after that expression is evaluated.
Not exactly the answer you are looking for, but have you thought about weak pointers? (for example, boost::weak_ptr). In this case, the original A would be held in a shared_ptr and the Wrapper constructor accepts a weak_ptr. The neat thing with this approach is that, before each usage of the weak_ptr, you can attempt to lock() which will give you a shared_ptr - if that fails, you know that A is gone and Wrapper cannot function... But it's handled cleanly...
This might do the job unless your class has public data members.
Basically, the idea is not to restrict the construction of the wrapper but to make sure that instances can be used (just like you said) only as long as they are temporary values. One can achieve this by overloading all methods and deleting (or making them private) those that refer to const&.
Here's a simple example:
class Wrapper
{
public:
Wrapper() = default;
Wrapper(const std::string& name) : name(name) {}
void process() && { std::cout << "Greetings from " << name << std::endl; }
// Only temporary instances of this class are allowed!
void process() const & = delete;
private:
std::string name;
};
And some use cases:
Wrapper("John").process(); // intended use case
Wrapper j; // create whatever you want
j.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
std::move(j).process(); // this is still possible
const Wrapper& t = Wrapper(); // bind the temporary to a const reference - not a problem because ...
t.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
The obvious disadvantages are:
You have to overload every public member function.
The error message is delayed and not very informative.
A similar thing has been done in the standard. The make routines for std::reference_wrapper do not accept temporaries.
Note that they considered another subtlety: the overload uses const T&& instead of T&&. This can be important in our case as well. For example, if your wrapper is deliberately designed to be noncopyable and you use make routines such as
const Wrapper make_wrapper();
instead of
Wrapper make_wrapper();
In this case, you might want to replace
void process() &&;
by
void process() const &&;
I'd not bother enforcing this at compile time, as there are always going to be corner cases where this would be overly restrictive, limiting the usefulness of the class, but rather wrap tools like valgrind or Purify so I can spot places where invalidated references are used.
I believe in C++17 and later you can get approximately what you want by doing the following:
Delete the move constructor for your type (and don't define a copy constructor).
Always accept your type by value in APIs.
So, for example:
#include <type_traits>
#include <utility>
// A non-moveable, non-copyable type.
struct CantMove {
CantMove(CantMove&&) = delete;
CantMove(int) {} // Some other constructor
};
static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);
// A function that accepts it by value.
bool AcceptByValue(CantMove input) { return true; }
// It's possible to call the value-accepting API when the input is a prvalue
// (which in previous versions of C++ would have been a temporary).
bool unused = AcceptByValue(CantMove(0));
// But it's not possible to call with a named value, even when casted to an
// rvalue reference. This doesn't compile.
CantMove cant_move(0);
bool unused_2 = AcceptByValue(std::move(cant_move));
It's possible to provide the value-accepting function with what we previously called a temporary because guaranteed copy elision says that there isn't even a temporary involved anymore—the only CantMove object created is the function parameter itself, so there is no move- or copy-construction involved. In contrast it's not possible to call with std::move(cant_move) because that would involve move-constructing the function parameter, and the type is not move-constructible.
Of course it's still possible to initialize a CantMove directly:
CantMove foo{0};
But if you own all of the APIs that accept a CantMove and make them all accept by value, then you can't actually do anything with foo afterward. This means it would be hard for a user to do this by mistake and not realize the problem.
Yes, you could.
You would make the constructor and regular copy-constructor/assign private but make the r-value move semantics (C++0x) public.
You would have a static or friend constructor to create the temporary.
In 2003 C++ you would also be able to use this to bind to a const reference.
Of course you'd have the issue that your const reference would probably become invalidated after the statement.

Swap method with const members

I want to implement a Swap() method for my class (let's call it A) to make copy-and-swap operator=(). As far as I know, swap method should be implemented by swapping all members of the class, for example:
class A
{
public:
void swap(A& rhv)
{
std::swap(x, rhv.x);
std::swap(y, rhv.y);
std::swap(z, rhv.z);
}
private:
int x,y,z;
};
But what should I do if I have a const member? I can't call std::swap for it, so I can't code A::Swap().
EDIT: Actually my class is little bit more complicated. I want to Serialize and Deserialize it. Const member is a piece of data that won't change (its ID for example) within this object. So I was thinking of writing something like:
class A
{
public:
void Serialize(FILE* file) const
{
fwrite(&read_a, 1, sizeof(read_a), file);
}
void Deserialize(FILE* file) const
{
size_t read_a;
fread(&read_a, 1, sizeof(read_a), file);
A tmp(read_a);
this->Swap(tmp);
}
private:
const size_t a;
};
and call this code:
A a;
FILE* f = fopen(...);
a.Deserialize(f);
I'm sorry for such vague wording.
I think what you really want is to have an internal data structure that you can easily exchange between objects. For example:
class A
{
private:
struct A_Data {
int x;
int y;
const int z;
A_Data(int initial_z) : z(initial_z) {}
};
std::auto_ptr<A_Data> p_data;
public:
A(int initial_z) : p_data(new A_Data(initial_z)) {}
void swap(A& rhv) {
std::swap(p_data, rhv.p_data);
}
};
This keeps the z value constant within any instance of A object internal data, but you can swap the internal data of two A objects (including the constant z value) without violating const-correctness.
After a good nights sleep I think the best answer is to use a non-const pointer to a const value -- after all these are the semantics you are trying to capture.
f0b0s, a good design principle is to design your objects to be immutable. This means that the object can't change once created. To "change" the object, you must copy the object and make sure to change the elements you want.
That being said, in this case you should look at using a copy constructor instead to copy the objects you want to swap, and then actually swap the references to the object. I can understand it'd be tempting just to be able to change the elements of an object under the hood, but it'd be better to make a copy of the object and replace the references to that object with the NEW object instead. This gets you around any const nastiness.
Hope this helps.
I suggest you use pointers to the instances. The pointers can be swapped much easier than the data in the class or struct.
The only way to swap a constant value is to create another object, or clone the current object.
Given a struct:
struct My_Struct
{
const unsigned int ID;
std::string name;
My_Struct(unsigned int new_id)
: ID(new_id)
{ ; }
};
My understanding is that you want to swap instances of something like My_Struct above. You can copy the mutable (non-const) members but not the const member. The only method to alter the const member is to create a new instance with a new value for the const member.
Perhaps you need to rethink your design.
IMHO you must consider not to swap CONST members.
PD: I think you could consider to use reflection in your approach. so you don't have to maintain the function.
This is why const_cast was created. Just remember not to shoot your foot off.
Edit: OK, I concede - const_cast wasn't made for this problem at all. This might work with your compiler, but you can't count on it and if demons come flying out of your nostrils, please don't blame me.
tl;dr; : It's Undefined Behavior.
Reference/reason: CppCon 2017: Scott Schurr “Type Punning in C++17: Avoiding Pun-defined Behavior, #24m52s +- ”
My interpretation, by example:
Suppose you create an object of type T, which have some const members. You can pass this object as a non-const reference to a function f(&T) that manipulates it, but you'd expect the const members to remain unalterable after the call. swap can be called in non-const references, and it can happen inside the function f, breaking the premise of const members to the caller.
Every part of your code that uses swap would have to assert that the object of type T being swapped does not belong to any context where the const members are assumed constant. That is impossible to automatically verify*.
*I just assumed that this is impossible to verify because it seems like an extension of the undecidability of the halting problem.

auto_ptr question in c++

I am new here.
I am also new on C++
So here is the class and function i wrote.But i got the compiler error
My class:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
Implement my class:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
My main() function here:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
I got the error:
error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
I do not know how to change it even after reading the document on this link:
The reason for the error is that you are calling the copy constructor of auto_ptr my_player in fooPlayerFactory::MakePlayerO() which is a const method. That means that is cannot modify its members.
However the copy constructor of auto_ptr DOES modify the right hand side so returning my_player trys to change its pointer to 0 (NULL), while assigning the original pointer to the auto_ptr in the return value.
The signature of the copy constuctor is
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
not
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
The copy constructor of auto_ptr assigns ownership of the pointer to the left hand side, the right hand side then holds nothing.
I don't think you want to use auto_ptr here, you probably want boost::smart_ptr
It looks like you have mixed up two uses for auto_ptr
The first is as poor man's boost::scoped_ptr. This is to manage a single instance of a pointer in a class, the class manages the life time of the pointer. In this case you don't normally return this pointer outside your class (you can it is legal, but boost::smart_ptr / boost::weak_ptr would be better so clients can participate the life time of the pointer)
The second is its main purpose which is to return a newly created pointer to the caller of a function in an exception safe way.
eg
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
As I said I think you have mixed these two uses auto_ptr is a subtle beast you should read the auto_ptr docs carefully. It is also covered very well in Effective STL by Scott Meyers.
In your code:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
This is a const function, but fooPlayerfunc is not const - my compiler reports this error rather than the one you say you are getting. Are you posting the real code?
I don't think you actually want to constructing dynamic objects here.
A factory object creates and returns an object it normally does not keep a reference to it after creation (unless you are sharing it), and I don't actually see anywhere that you are creating the player.
If you only ever create one player internally in your (fooPlayerFactory). Then create an object and return references to it.
Edit: in response to the comment (which is correct, my bad), I left only the advice part.
Best practice is to have the factory methods just return a plain old pointer to the underlying object, and let the caller decide how to manage ownership (auto_ptr, scoped_ptr, or whatever).
Also your code is buggy, any class that implements virtual methods should have a virtual destructor.
I'm not seeing anywhere you construct my_player, so I have a feeling that some of the code is missing. Specifically, I think your constructor has this line:
my_player = new fooPlayer()
A fooPlayer object is not quite the same thing as an auto_ptr<fooPlayer> object, and auto_ptr is intentionally designed to prevent assigning from one to the other because, frankly, the alternative is worse. For the details, look up (1) conversion constructors, (2) the explicit keyword, and (3) copy constructors and destructive copy semantics.
You should change the constructor to either:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
Or (using a member initializer list):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
The solution isn't pretty but, like I said, the alternative is worse due to some really arcane details.
As a bit of advice, though, you're making life harder than it needs to be; and may in fact be causing strange bugs. auto_ptr exists to manage the lifetime of an object, but the only reason you need to worry about the lifetime of my_player is that you've allocated it with new. But there's no need to call new, and in fact there's no need to keep my_player. And unless fooPlayerFactory is meant to be the base class for some other factory, there's no need to mark functions virtual.
Originally I thought you could get away with simply returning copies of the my_player object, but there's a problem: before returning my_player from MakePlayer() you call a method on it, and I assume that method changes the internal state of my_player. Further calls to MakePlayer() will change the state again, and I think you're going to eventually have my_player in the wrong state. Instead, return a different fooPlayer object with each request. Don't do memory management, just promise to construct the object. That way the user can decide on memory allocation:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
I would change fooPlayerFactory to look like this:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};