Late non-copyable member initialization - c++

I'm trying to initialize a object's member that cannot be assigned nor copied. I need some other tasks to be performed first and the initialization depends on it, so I have to delay it.
#include <boost/process.hpp>
class A{
std::unique_ptr<boost::process::child> child_;
std::unique_ptr<boost::process::pistream> is;
A(std::string exec, boost::process::context process_context){
// Stuff that needs to be done first
// ...
child_ = std::make_unique<boost::process::child>(start_child(exec, process_context));
is = std::make_unique<boost::process::pistream>(child_->get_stdout()); // <- error
}
boost::process::child start_child(std::string exec, boost::process::context process_context);
};
The error I get from this is:
error C2280:
'std::basic_ios>::basic_ios(const
std::basic_ios> &)' : attempting to
reference a deleted function
If I understand this correctly, somewhere in that line a copy is happening, which isn't allowed.
The unique pointers are not required. I just use them to avoid another error (no default initialization) but I would be happy to accept suggestions both with or without them.

You can use boost::optional<> for lazy initialization like this.
Live On Coliru
#include <memory>
#include <boost/optional.hpp>
struct pistream { };
struct child {
pistream& get_stdout() { return is; }
pistream is;
};
struct context { };
class A {
std::unique_ptr<child> child_;
boost::optional<pistream&> is;
A(std::string, context) {
// Stuff that needs to be done first
// ...
child_ = std::make_unique<child>();
is = child_->get_stdout();
}
};

The problem is that std::unique_ptr wants ownership of the pistream, so it tries to take a copy, which as you have discovered isn't allowed. If you think about it, this makes sense: you certainly don't want std::unique_ptr<b::p::pistream> deleting _child's stream in its destructor.
The easiest solution would be to just use a regular, non-owning pointer instead, say:
class A{
std::unique_ptr<boost::process::child> child_;
boost::process::pistream* is = nullptr;
A(std::string exec, boost::process::context process_context){
// ...
child_ = std::make_unique<boost::process::child>(start_child(exec, process_context));
is = &child_->get_stdout();
}
};
Of course, you'd want to check that is is not nullptr before actually using it, but the same is true for a unique_ptr.

Related

trying to insert a vector to an unordered_map but get "message : see reference to class template instantiation"

I'm trying to make an ecs and this is my code
#include "pandaFramework.h"
#include "pandaSystem.h"
#include <unordered_map>
#include <vector>
#include <memory>
#include <iostream>
struct Component {
NodePath* node_path;
Component(NodePath* path) {
node_path = path;
}
void start(){}
void update(){}
};
struct Spinner : Component {
void update() {
std::cout << "Hello World!\n";
}
};
class Scene : public NodePathCollection {
public:
std::unordered_map<NodePath*, std::vector<std::unique_ptr<Component>>> components;
void add_path(NodePath node_path) {
NodePathCollection::add_path(node_path);
std::vector<std::unique_ptr<Component>> empty;
components[&node_path] = std::move(empty);
}
template<typename ComponentType>
void add_component(NodePath* node_path) {
components[node_path].push_back(std::make_unique<ComponentType>(node_path));
}
};
int main(int argc, char* argv[]) {
// Load the window and set its title.
PandaFramework framework;
framework.open_framework(argc, argv);
framework.set_window_title("My Panda3D Window");
WindowFramework* window = framework.open_window();
// Load the environment model.
NodePath scene = window->load_model(framework.get_models(), "models/environment");
Scene s;
s.add_path(scene);
s.add_component<Spinner>(&scene);
// Reparent the model to render.
scene.reparent_to(window->get_render());
// Apply scale and position transforms to the model.
scene.set_scale(0.25f, 0.25f, 0.25f);
scene.set_pos(-8, 42, 0);
// Run the engine.
framework.main_loop();
// Shut down the engine when done.
framework.close_framework();
return 0;
}
And when I use add_object I get
"message : see reference to class template instantiation 'std::vectorstd::unique_ptr<Component,std::default_delete<Component>,std::allocatorstd::unique_ptr<Component,std::default_delete<Component>>>' being compiled"
What should I do?
There are multiple fundamental bugs with the shown code.
You will get the same compilation error with the following code, as well:
std::vector<std::unique_ptr<Component>> empty;
std::vector<std::unique_ptr<Component>> empty2=empty;
A std::unique_ptr, by definition, a one and only pointer to the same underlying object. There are no others. For that reason is why std::unique_ptr does not have a copy constuctor. A std::unique_ptr cannot be copied. This is an absolute rule. No exceptions. The above code attempts to copy a vector of std::unique_ptrs. Since they cannot be copied, this fails. The fact that, in this instance, the vectors are empty is immaterial.
void add_object(Object object) {
std::vector<std::unique_ptr<Component>> empty;
components[&object] = empty;
}
The assignment operator effectively attempts to make a copy of the vector, and this fails for the same reason.
It's possible to make this work using move semantics:
components[&object] = std::move(empty);
This will now compile. But now you have a different bug to deal with.
object is a parameter to this function.
When this function returns, all of its parameters get destroyed. They will no longer exist. They will cease to exist. They will become no more. They will be come ex-objects.
And the code above will be left with a pointer to a destroyed object in the unordered map. Whatever happens to touch that pointer, from that point on, by definition, will be undefined behavior. You will need to fix this as well.
The problem is very layered, as mentioned in Sam's answer. One problem is that you lack a proper copy constructor for the Component class. This can be solved by not using a temporary variable as shown in the code below:
class Scene {
public:
std::unordered_map<Object*, std::vector<std::unique_ptr<Component>>> components;
void add_object(Object object) {
// std::vector<std::unique_ptr<Component>> empty;
// Adding an empty container at the given key
components[&object] = std::vector<std::unique_ptr<Component>>();
}
};
For the other problems Sam's mentions in his answers, perhaps, instead of using a pointer to an Object, you could use the object instead. This could also lead to the same copy constructor issue, but the code should work with minimal changes.

Overload -> arrow operator in shared_ptr<interface> instance with no pure virtual destructor in interface

I'm trying to overload the -> operator to eventually execute something along the lines:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
Note: I have no control over MyInterface, cannot implement the pure virtual destructor.
Here is what I tried (the below code runs):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
Output:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
To reiterate:
This code doesn't compile:
sharedPtrWrapper->Toggle();
How to make it compile?
Edit : I'm using a wrapper because I have no control over the MyInterface, I get it from a library, also shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance); doesn't compile, because of the missing pure virtual destructor from the above mentioned interface.
Edit2: Example library usage in pseudocode:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
The problem is, that shared_ptr behaves like a pointer and Wrapper does that as well. In summary, you have code that behaves like a pointer to a pointer. In short, you could call (*sharedPtrWrapper)->Toggle(); instead of the abomination sharedPtrWrapper->operator->()->Toggle();.
Careful though: It's unclear what all this is supposed to achieve, because the example code is just an abstraction of your actual code. So, maybe it would just be more elegant to put a forwarding Toggle() method into class Wrapper, but that's impossible to tell with the info provided here.
I am confused about the question. Why wrapper class that does nothing?
If you want to put a class inside shared pointer yet do something uncommon at destruction: like, calling dll's function that performs the destruction, do some preprocessing, perform file closure instead of delete, or do nothing at all if that's what you want. Then you can simply specify it at shared pointer instantiation:
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - see construction option 5.
You don't need your wrapper at all.
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
wont work because MyInterface is an abstract class. But, just like you can do
MyInterface *myInstance = new A();
To have a MyInterface * that points to a concrete derived object, you can use
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
To get a std::shared_ptr<MyInterface> that points to a concrete derived object. You can then use sharedPtr to access Toggle like
sharedPtr->Toggle();
You can see that working in this live example
sharedPtrWrapper->Toggle(); doesn't compile because of operator-> chaining rules explained well in this answer. In principle: if your object is NOT a pointer, operator-> is called recursively, if it is a pointer, member access is performed. Now std::shared_ptr has overloaded operator-> to access the raw Wrapper<MyInterface>* pointer kept inside and when it is applied on it, it tries to access Toggle, which does not exist.
For clarity note that this code also will not compile:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
You can do this however:
(*sharedPtrWrapper)->Toggle();
Use:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr has type-erased destruction, there is no need for a virtual destructor.

Avoid use of undefined object in c++

If I create a class in c++, it is possible to call a function of an object of this class, even if this class does not exists.
For example:
Class:
class ExampleClass
{
private:
double m_data;
public:
void readSomeData(double param)
{
m_data = param;
}
}
Any function where this class is used:
int main()
{
ExampleClass* myClass;
myClass->readSomeData(2.5);
}
Ofcourse this wouldn't function, because myClass is not defined.
To avoid such situations, I check if ExampleClass objects are a null_ptr
example:
void readSomeData(double param)
{
if(this == null_ptr)
return;
m_data = param;
}
But gcc says:
'this' pointer cannot be null in well-defined C++ code; comparison may
be assumed to always avaluate to false.
Ofcourse that is only a warning, but I think it is not nice to have this warning. Is there a better way to check if the pointer of a class is defined?
Testing it in the class is the wrong way, the warning is correct about that if your code is well defined then this must not be null, so the test should happen at the time when you call the member function:
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
if (myClass != nullptr) {
myClass->readSomeData(2.5);
}
return 0;
}
If a pointer must not be null at a certain part of your code then you should do it according to CppCoreGuideline: I.12: Declare a pointer that must not be null as not_null
Micorosoft provides an Guidelines Support Library that has an implementation for not_null.
Or if possible then don't use pointers at all but std::optional.
So a code setup could look like this:
#include <gsl/gsl>
struct ExampleClass {
void readSomeData(double ){}
};
// now it is clear that myClass must not and can not be null within work_with_class
// it still could hold an invalid pointe, but thats another problem
void work_with_class(gsl::not_null<ExampleClass*> myClass) {
myClass->readSomeData(2.5);
}
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
work_with_class(myClass);
return 0;
}
The best way is not use pointers at all:
int main()
{
ExampleClass myClass;
myClass.readSomeData(2.5);
}
That way there's no need for any check, and in fact, checking this inside the function is moot.
If you need nullability, use std::optional instead.
Either don't use pointers as Bartek Banachewicz has pointed out, or properly initialize and check the pointer:
int main()
{
ExampleClass* myClass= 0;
if (myClass)
myClass->readSomeData(2.5);
return 0;
}
Of course you still have to add the instantiation of the object at some point, otherwise the code is nonsense.

C++ How to avoid access of members, of a object that was not yet initialized

What are good practice options for passing around objects in a program, avoiding accessing non initialized member variables.
I wrote a small example which I think explains the problem very well.
#include <vector>
using namespace std;
class container{public:container(){}
vector<int> LongList;
bool otherInfo;
};
class Ship
{
public:Ship(){}
container* pContainer;
};
int main()
{
//Create contianer on ship1
Ship ship1;
ship1.pContainer = new container;
ship1.pContainer->LongList.push_back(33);
ship1.pContainer->otherInfo = true;
Ship ship2;
//Transfer container from ship1 onto ship2
ship2.pContainer = ship1.pContainer;
ship1.pContainer = 0;
//2000 lines of code further...
//embedded in 100 if statements....
bool info = ship1.pContainer->otherInfo;
//and the program crashes
return 0;
}
The compiler cannot determine if you are introducing undefined behavior like shown in your example. So there's no way to determine if the pointer variable was initialized or not, other than initializing it with a "special value".
What are good practice options for passing around objects in a program, avoiding accessing non initialized member variables.
The best practice is always to initialize the pointer, and check before dereferencing it:
class Ship {
public:
Ship() : pContainer(nullptr) {}
// ^^^^^^^^^^^^^^^^^^^^^
container* pContainer;
};
// ...
if(ship1.pContainer->LongList) {
ship1.pContainer->LongList.push_back(33);
}
As for your comment:
So there are no compiler flags that could warn me?
There are more simple and obvious cases, where the compiler may leave you with a warning:
int i;
std::cout << i << std::endl;
Spits out
main.cpp: In functin 'int main()':
main.cpp:5:18: warning: 'i' is used uninitialized in this function [-Wuninitialized]
std::cout << i << std::endl;
^
See Live Demo
One good practice to enforce the checks is to use std::optional or boost::optional.
class Ship
{
public:
Ship() : pContainer(nullptr) {}
std::optional<container*> Container()
{
if(!pContainer)
return {};
return pContainer;
}
private:
container* pContainer;
};
It will force you (or better: provide a firm reminder) to check the result of your getter:
std::optional<container*> container = ship1.Container();
container->otherInfo; // will not compile
if(container)
(*container)->otherInfo; // will compile
You would always need to check the result of operation if you use pointers. What I mean is that with optional the situation is more explicit and there's less probability that you as the programmer will forget to check the result.
It seems that you are looking for a way to make your code
bool info = ship1.pContainer->otherInfo;
work even though the pContainer may be null.
You can use a sentinel object, which holds some default data:
container default_container;
default_container.otherInfo = false; // or whatever the default is
Then use a pointer to the sentinel object instead of a null pointer:
//Transfer container from ship1 onto ship2
ship2.pContainer = ship1.pContainer;
ship1.pContainer = &default_container; // instead of 0
//2000 lines of code further...
//embedded in 100 if statements....
bool info = ship1.pContainer->otherInfo;
If you use this, you should make sure the sentinel object cannot be destroyed (e.g. make it a static member, or a singleton).
Also, in the constructor, initialize your pointers so they point to the sentinel object:
class Ship
{
public: Ship(): pContainer(&default_container) {}
...
};
I found an additional solution. It is admittedly not preventing the access of uninitialized objects, but at least the program crashes AND returns an error message, that enables us to correct our mistake. (This solution is particularly for the g++ compiler.)
First of all set the compiler flag _GLIBCXX_DEBUG. Then instead of naked pointer use unique_ptr.
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class container{
public:container(){}
int otherInfo = 33;
};
class Ship
{
public:Ship(){}
std::unique_ptr<container> upContainer;
};
int main()
{
Ship ship1;
cout<<ship1.upContainer->otherInfo<<endl;
return 0;
}
This code will produce an error:
std::unique_ptr<_Tp, _Dp>::pointer = container*]: Assertion 'get() != pointer()' failed.
Hence telling us that we should probably include an if(ship1.upContainer) check.
What are good practice options for passing around objects in a program, avoiding accessing non initialized member variables.
Good practice would be to initialize everything in the constructor.
Debatable better practice is to initialize everything in the constructor and provide no way of modifying any members.

Best Practice for Scoped Reference Idiom?

I just got burned by a bug that is partially due to my lack of understanding, and partially due to what I think is suboptimal design in our codebase. I'm curious as to how my 5-minute solution can be improved.
We're using ref-counted objects, where we have AddRef() and Release() on objects of these classes. One particular object is derived from the ref-count object, but a common function to get an instance of these objects (GetExisting) hides an AddRef() within itself without advertising that it is doing so. This necessitates doing a Release at the end of the functional block to free the hidden ref, but a developer who didn't inspect the implementation of GetExisting() wouldn't know that, and someone who forgets to add a Release at the end of the function (say, during a mad dash of bug-fixing crunch time) leaks objects. This, of course, was my burn.
void SomeFunction(ProgramStateInfo *P)
{
ThreadClass *thread = ThreadClass::GetExisting( P );
// some code goes here
bool result = UseThreadSomehow(thread);
// some code goes here
thread->Release(); // Need to do this because GetExisting() calls AddRef()
}
So I wrote up a little class to avoid the need for the Release() at the end of these functions.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * Thread() const { return m_T; }
};
So that now I can just do this:
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC.Thread());
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}
What I don't like is that to access the thread pointer, I have to call a member function of ThreadContainer, Thread(). Is there some clever way that I can clean that up so that it's syntactically prettier, or would anything like that obscure the meaning of the container and introduce new problems for developers unfamiliar with the code?
Thanks.
use boost::shared_ptr
it is possible to define your own destructor function, such us in next example: http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html#com
Yes, you can implement operator ->() for the class, which will recursively call operator ->() on whatever you return:
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * operator -> () const { return m_T; }
};
It's effectively using smart pointer semantics for your wrapper class:
Thread *t = new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
You could also write a conversion function to enable your UseThreadSomehow(ThreadContainer tc) type calls in a similar way.
If Boost is an option, I think you can set up a shared_ptr to act as a smart reference as well.
Take a look at ScopeGuard. It allows syntax like this (shamelessly stolen from that link):
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
Or you could try Boost::ScopeExit:
void World::addPerson(Person const& aPerson) {
bool commit = false;
m_persons.push_back(aPerson); // (1) direct action
BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
{
if(!commit)
m_persons.pop_back(); // (2) rollback action
} BOOST_SCOPE_EXIT_END
// ... // (3) other operations
commit = true; // (4) turn all rollback actions into no-op
}
I would recommend following bb advice and using boost::shared_ptr<>. If boost is not an option, you can take a look at std::auto_ptr<>, which is simple and probably addresses most of your needs. Take into consideration that the std::auto_ptr has special move semantics that you probably don't want to mimic.
The approach is providing both the * and -> operators together with a getter (for the raw pointer) and a release operation in case you want to release control of the inner object.
You can add an automatic type-cast operator to return your raw pointer. This approach is used by Microsoft's CString class to give easy access to the underlying character buffer, and I've always found it handy. There might be some unpleasant surprises to be discovered with this method, as in any time you have an implicit conversion, but I haven't run across any.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
operator ThreadClass *() const { return m_T; }
};
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC);
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}