Call a member function automatically in the end of a scope - c++

Is there a way to call a class member function automatically in the end of a scope?
Apparently if the class is instantiated within the same scope, clean() can be used in the destructor of it. The question is, can we achieve that if it is instantiated before the scope? In detail:
class foo
{
public:
void do_something() {}
void clean() {}
};
int main()
{
foo c;
{
c.do_something();
// do something
// call c.clean() automatically
}
}

Something like this. May not be exactly what you are looking for as it requires you do declare another variable at the start of the scope where you want the clean function to be called.
class CleanFoo
{
public:
CleanFoo(Foo& r) : ref(r) {}
~CleanFoo() { ref.clean(); }
CleanFoo(const CleanFoo&) = delete;
CleanFoo& operator=(const CleanFoo&) = delete;
private:
Foo& ref;
};
int main()
{
foo c;
{
CleanFoo cc(c);
...
} // c.clean() will be called here
...
}

std::unique_ptr actually has something like that, in the form of a second parameter you can pass to the constructor, a deleter. The deleter cleans up when the std::unique_ptr object goes out of scope. Normally (i.e. if you don't specify it) it would be std::default_delete that calls delete on the dynamically allocated memory it owns. But you can make it do other things, like this:
#include <cstdio>
#include <memory>
class foo
{
public:
void do_something() { printf("do_something\n"); }
void clean() { printf( "clean\n"); }
};
int main()
{
foo c;
{
std::unique_ptr<foo, void(*)(foo*)> scoped_cleaner(&c, [](foo* c) { c->clean(); });
c.do_something();
}
}
godbolt

Only thing that is called automatically at the end of the scope is the destructors of the objects whose lifetime end in that scope. As such, you could have another object local to the inner scope whose destructor calls the function.
A generic solution exists in Boost already:
foo c;
{
BOOST_SCOPE_EXIT(&c) {
c.clean();
};
c.do_something();
// do something
}
One caveat with all these answers including mine is that foo::clean() must not throw.

Write a do_guard. You can leverage RAII to create a wrapper that will call do on the object you give the wrapper in it's constructor, and then the destructor will call clear. That would look like
struct do_guard
{
foo& ref;
do_guard(foo& ref) : ref(ref) { ref.do_something(); }
~do_guard() { ref.clean(); }
};
int main()
{
foo c;
{
do_guard guard(c);
// do something
} // guard.~do_guard() will call c.clean() automatically
}

You can make do_something return something that gets its destructor called at the end of the scope:
class foo;
struct cleaner {
foo& f;
cleaner(foo& f) : f{f} {}
~cleaner();
};
class foo
{
public:
cleaner do_something() { return *this; }
void clean() {}
};
cleaner::~cleaner() { f.clean(); }
int main()
{
foo c;
{
auto x = c.do_something();
// do something
} // x calls c.clean() automatically
}

Related

C++ create static object without constructing it (without allocation)

Im writing embedded code that cannot use memory allocation!
Also, static objects (therefore constructed before the microcontroller has executed the main funtion with all its initialization) shall be constructed within the main after the initialization, not before.
The only solution people suggest is to use static object pointers and allocate (construct them with new) during initialization. since this is no option for me, is there no other solution?
what i wanna do is as follows:
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
}
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
void init()
{
// now i wanna construct myObjectA
myObjectA(123, false);
}
private:
char myChar1;
A myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
}
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
You can use a storage area large enough to create there an instance of A and placement new to control the time you create it.
As an example:
#include
#include
struct A {
A(int a, bool b): myVal1(a), myVal2(b) {}
void foo() {}
private:
int myVal1;
bool myVal2;
};
struct B {
B(char x): myChar1(x) {}
~B() { if(ptr) { ptr->~A(); } }
void init() {
ptr = new (&storage) A{123, false};
}
A * myObjectA() {
return ptr;
}
private:
char myChar1;
std::aligned_storage_t<sizeof(A), alignof(A)> storage;
A *ptr{nullptr};
};
static B myObjectB('F');
void global_init() {
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main() {
global_init();
myObjectB.myObjectA()->foo();
}
This won't allocate memory (if I got right what you mean for that) and the instance of A is actually created within B::init (that seems to be a requirement from what you wrote in your question).
If you have access to a compiler that supports C++17 or you can use the C++ Boost Libraries, std::optional is a valid alternative as suggested in another answer. Anyway you didn't specify the revision of the standard to which to adhere, so... Here is a way to go in any case.
Do you have boost available?
#include <boost/optional.hpp>
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
};
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
A& getA() {
assert(myObjectA);
return myObjectA.get();
}
void init()
{
// now i wanna construct myObjectA
myObjectA.emplace(123, false);
}
private:
char myChar1;
boost::optional<A> myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
};
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main()
{
global_init();
}

Inheritance and smart pointers (std::shared_ptr)

There are a lot of things that needs to be said. First off, I would like to know if the approach below is considered a design pattern or even a common technique (That's why I didnt provide further information on the title). If thats the case, whats the name?
Anyways, this is a minified version of what I'm trying to achieve. Since I need to use copying, I found that using std::shared_ptr is the best to avoid deallocated (deleted) pointers.
class Foo
{
public:
Foo() : ptr(nullptr) {}
Foo(const Foo& foo) : ptr(foo.ptr) {}
virtual ~Foo() = default;
void whatever() {
if (ptr)
ptr->whateverHandler();
}
void reset() {
ptr.reset();
}
void resetBar() {
ptr.reset(new Bar);
}
// Other resets here...
protected:
Foo(Foo* foo) : ptr(foo) {}
private:
// Every child class should override this
virtual void whateverHandler() {
throw "whateverHandler cant be called within base class";
}
protected:
std::shared_ptr<Foo> ptr;
};
class Bar : public Foo
{
public:
Bar() : Foo(this) {}
void whateverHandler() {
printf("Bar's handler!!! \n");
}
};
This all looks good and compiles fine, however, the following exame crashes. Why is that?
int main()
{
{
Foo f;
f.resetBar();
}
return getchar();
}
Bar() : Foo(this) {}
Be careful when you pass this to a shared_ptr.
Think about what will happen afterf.resetBar(); and ptr.reset(new Bar); again.
For new Bar, an object of type Bar will be constructed, and inside its constructor this is passed to the parent class member ptr, then the object is managed by the it which is a std::shared_ptr.
After that, the object is managed by f.ptr; which is another std::shared_ptr.
So there're two std::shared_ptrs pointing to the same object, but std::shared_ptrs don't know anything about that; because you're constructing them separately. When f and f.ptr is destroyed, the pointed-to object will be destroyed too. Then the member ptr will be destroyed, it will try to destroyed the same object again, which leads to UB.
I'm not sure about what the design trying to accomplish, but just stopping passing this to a std::shared_ptr could eliminate UB.
class Foo
{
public:
virtual ~Foo() = default;
void whatever() {
if (ptr)
ptr->whateverHandler();
}
void reset() {
ptr.reset();
}
void resetBar() {
ptr.reset(new Bar);
}
// Other resets here...
private:
// Every child class should override this
virtual void whateverHandler() = 0;
std::shared_ptr<Foo> ptr;
};
class Bar : public Foo
{
public:
void whateverHandler() {
printf("Bar's handler!!! \n");
}
};
int main()
{
{
Foo f;
f.resetBar();
f.whatever();
f.resetSthElse();
f.whatever();
}
}
And IMO, having a member of type std::shared_ptr pointing to derived class is confusing; separating it might be better. And then, I think it might be the bridge design partern.
class Foo
{
public:
void whatever() {
if (ptr)
ptr->whateverHandler();
}
void reset() {
ptr.reset();
}
void resetBar() {
ptr.reset(new BarHandler);
}
// Other resets here...
private:
std::shared_ptr<FooHandler> ptr;
};
class FooHandler
{
public:
virtual ~FooHandler() = default;
// Every child class should override this
virtual void whateverHandler() = 0;
};
class BarHandler : public FooHandler
{
public:
void whateverHandler() {
printf("Bar's handler!!! \n");
}
};
int main()
{
{
Foo f;
f.resetBar();
f.whatever();
f.resetSthElse();
f.whatever();
}
}
The Foo::ptr holds a pointer to its mother Foo(this) with reference count 1.
In Foo::resetBar(), when Foo asking Foo::ptr to call reset(new Bar), Foo::ptr gave up its ownership to its mother Foo(this) and found out the reference count was already decreased to 0, so it need to kill Foo.
When the Foo is dead, its children are killed. So Foo::ptr must be dead, too. Then assigning the new Bar to dead Foo::ptr causes UB.

How to properly use std::shared_from_this or trick around it?

Question for C++ experts: I've got a library function expecting a shared_ptr<T> and I'd like to call this function within T. I know share_from_this is the correct way to go, but I can't get my head around it (and how to use it properly).
I've come up with a trick and I'd like to know if its safe (no UB). If it's not, could you explain me how to use share_from_this in my case?
#include <memory>
template<class T>
void library_function(std::shared_ptr<T>)
{}
struct A {
std::shared_ptr<A> share()
{
return std::shared_ptr<A>(this, [](A*){});
}
void operator()()
{
library_function(share());
}
};
int main()
{
A a;
a();
}
First of all , the object you want to share_from_this needs to be previously shared object and managed by std::shared_ptr. Ensuring that, classes that allow it need publicly inherit from std::enable_shared_from_this<A>. Next, if you want to create shared pointer from this you need to use method shared_from_this().
With your current code, it's safe.
However, if library_function stores that shared_ptr to use later and a is destroyed because of out of scope. It's undefined behavior. It's not safe then. This sample code is not much different from your code but it has undefined behavior in the second call:
template<class T>
void library_function(std::shared_ptr<T> t)
{
static std::shared_ptr<T> s;
if (!s) {
s = t;
}
if (s) s->do_something();
}
struct A {
std::shared_ptr<A> share()
{
return std::shared_ptr<A>(this, [](A*){});
}
void operator()()
{
library_function(share());
}
void do_something() {
}
};
int main()
{
// This emulates some function call and go out of scope
{
A a;
a();
}
// This call is undefined behavior
library_function(std::shared_ptr<A>{});
}
The right way to do it is something like this:
#include <memory>
#include <iostream>
template<class T>
void library_function(std::shared_ptr<T> t)
{
static std::shared_ptr<T> s;
if (!s) {
s = t;
}
if (s) s->do_something();
}
struct A : std::enable_shared_from_this<A> {
~A() {std::cout << "Destructed\n"; }
std::shared_ptr<A> share()
{
return shared_from_this();
}
void operator()()
{
library_function(share());
}
void do_something() {
std::cout << "do_something\n";
}
};
int main()
{
// This emulates some function call and go out of scope
{
std::shared_ptr<A> a = std::make_shared<A>();
(*a)();
}
library_function(std::shared_ptr<A>{});
}
You should derive your class from std::enable_shared_from_this. Make sure your object is managed by a std::shared_ptr.
#include <memory>
template<class T>
void library_function(std::shared_ptr<T>)
{}
struct A : public std::enable_shared_from_this<A> {
void operator()()
{
library_function(shared_from_this());
}
};
int main()
{
auto a = std::make_shared<A>();
a->operator()();
}
Your class should derive from std::enable_shared_from_this<>, then you can call this->shared_from_this() to get a shared_ptr<> to it.
For example:
class foo : std::enable_shared_from_this<foo> {
public:
void bar() {
call_some_func(this->shared_from_this());
}
};
So call_some_func() will receive a shared pointer to the foo instance. This will work as the original instance is already in a shared pointer, i.e. the instance is created as:
auto foo_inst = std::make_shared<foo>();

C++ initializer list capabilities: call functions without initializing member?

This is a question on the syntax of C++ initializer lists.
Is it possible to call functions from initializer lists without them being arguments to member object constructors?
Code example listed below is paraphrased (paracoded?) from a similar situation at work.
The Situation
A member variable takes a pointer to a singleton as constructor
argument.
The member variable is constructed by initializer list in its containing class' constructor.
The singleton has not been created prior to the containing class being constructed.
The Code
#include <iostream>
#define LOG { std::cout << __PRETTY_FUNCTION__ << std::endl; }
namespace
{
template <class T>
class SingletonService
{
public:
static T* Instance() { LOG; return mpT; }
static void InstallInstance(T* pT) { LOG; mpT = pT; }
static void DeleteInstance() { if (mpT) delete mpT; }
protected:
static T* mpT;
};
template <class T>
T* SingletonService<T>::mpT = NULL;
class OneOfMe
{
public:
OneOfMe() { LOG; };
virtual ~OneOfMe() { };
};
class Container
{
public:
Container(OneOfMe* pObj) { LOG; /* Do something with pObj */ }
virtual ~Container() { }
};
int GenerateNum()
{
return 42;
}
class Baz
{
public:
Baz(int num) : mNum(num) { LOG; }
virtual ~Baz() { }
protected:
int mNum;
};
class Bar
{
public:
Bar() : mBaz(GenerateNum()) { LOG; } // Perfectly OK to call function that is argument to member object's non-default ctor.
virtual ~Bar() { };
protected:
Baz mBaz;
};
class Foo
{
public:
Foo()
: SingletonService<OneOfMe>::InstallInstance(new OneOfMe) // Compile error
, mContainer(SingletonService<OneOfMe>::Instance()) { }
virtual ~Foo() { };
protected:
Container mContainer;
};
}
int main(int argc, char* argv[])
{
LOG;
Bar bar;
SingletonService<OneOfMe>::InstallInstance(new OneOfMe); // This works.
Container container(SingletonService<OneOfMe>::Instance()); // And this works.
SingletonService<OneOfMe>::DeleteInstance();
return 0;
}
The compile error
>g++ main.cpp
main.cpp: In constructor ‘<unnamed>::Foo::Foo()’:
main.cpp:45: error: expected class-name before ‘(’ token
main.cpp:45: error: no matching function for call to
‘<unnamed>::Container::Container()’
main.cpp:37: note: candidates are:
<unnamed>::Container::Container(<unnamed>::OneOfMe*)
main.cpp:35: note:
<unnamed>::Container::Container(const<unnamed>::Container&)
main.cpp:45: error: expected ‘{’ before ‘(’ token
The Question
Is it syntactically possible to call a function from a class constructor's initializer list without being an argument to a member object's non-default constructor?
The question is for academic curiosity. I know at least one other solutions is to instantiate the singleton before creating the containing class.
You can utilize the comma operator.
In your example
class Foo
{
public:
Foo()
: mContainer((SingletonService<OneOfMe>::InstallInstance(new OneOfMe),
SingletonService<OneOfMe>::Instance()))
{}
virtual ~Foo();
protected:
Container mContainer;
};
Note the additional parentheses around the two expressions, otherwise these would be interpreted as two instead of one parameter.
Another approach to this particular problem could be to return the singleton from InstallInstance() as well, e.g.
template <class T>
class SingletonService {
public:
static T *InstallInstance(T *pT) { LOG; return mpT = pT; }
};
and then
class Foo {
public:
Foo()
: mContainer(SingletonService<OneOfMe>::InstallInstance(new OneOfMe)) {}
virtual ~Foo();
protected:
Container mContainer;
};
Is it possible to call functions from initializer lists without them being arguments to member object constructors?
Something like this maybe works as intended:
void f() {}
struct S {
S(): i{(f(), 0)} {}
int i;
};
int main() {
S s;
}
The basic idea is to rely on the comma operator. In this case, the value returned by the function (if any) is discarded and not used to initialize a member.
Of course, we still exploit the fact that a data member exists, so maybe it is not exactly what you are looking for.
If you want to get rid completely of data members, you can do something similar with a delegated constructor like in the following example:
void f() {}
class S {
S(int) {}
public:
S(): S{(f(), 0)} {}
};
int main() {
S s{};
}
No matters what's the return type of the invoked function. By means of the comma operator, the int value is used as a tag to dispatch the call to the right compiler and then it is discarded.

How to do lazy construct in C++?

I want to make 'lazy construct' in a C++ class, a simple method to do that is something like this:
#include "b.hpp" // class B
class A {
public:
// invoke B() in b.hpp, this constructor do not actually do init
A(int v_in) : v(v_in) {}
void foo() {
if(flag == false) {
b = create_B_obj();
flag = true;
}
}
private:
B create_B_obj() {
// some expensive ops
//...
}
private:
bool flag = false;
B b;
int v;
};
But a existing problem is that B may not contain a default constructor (B()), so how can I do 'lazy construct' in this case?
BTW: class B in my project is something like a socket which need to do connect or do bind-like calls, so I want to put these expensive ops lazy.
Use pointer, preferably smart pointer.
class A
{
public:
void foo() {
if( pb == nullptr ) {
pb.reset(create_B_obj());
}
}
private:
B* create_B_obj(); //or return std::unique_ptr
private:
std::unique_ptr<B> pb;
int v;
};
You could avoid the dynamic allocation if you use placement-new instead, in which case you need custom deleter with std::unique_ptr:
class A
{
public:
void foo() {
if( pb == nullptr ) {
pb.reset(create_B_obj());
}
}
private:
B* create_B_obj()
{
return new (buffer) B( /* arguments */);
}
private:
std::unique_ptr<B, PlacementNewDeleter> pb;
alignas(B) char buffer[sizeof(B)]; //buffer used by placement new
int v;
};
where PlacementNewDeleter defined as:
struct PlacementNewDeleter
{
template<typename T>
void operator(T const *obj) const { obj->~T(); }
};
Hope that helps.
If you don't have access on the B class, then the easier way to do this is to use a pointer.
std::unique_ptr<B> b;
Then if your foo method:
B foo()
{
if (! b)
b.reset(new B(/* params */));
// or b.reset(create_B_obj());, which should return a pointer (may also return an unique_ptr)
return b;
}
The std::unique_ptr overloads operator bool and manages the memory so you don't have to delete.
Note: I changed the return type of the foo method as it seems more logical like this.