I am using a pattern like this, C++11:
class FooViewController {
void build() {
auto label = ...
network->doWork([] (const Result& r) {
label->setText(r.text);
});
}
}
FooViewController may deconstruct before doWork completes, causing crashes. Looking at boost::signals2, I'm thinking of using boost::signals2::trackable, which works great for my single threaded purposes, with the benefit that I do not have to hold and manage my connections directly, however I'm not sure how to get such a solution working with lambdas.
Here is a working lambda free version:
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!");
}
};
Usage:
boost::signals2::signal<void()> signal;
{
Foo test;
signal.connect(boost::bind(&Foo::bar, &test));
signal();
}
signal();
Output:
Fired!
// Note a second 'Fired!' did not occur, which is correct behavior
Two goals:
1-- I'd like to do something like:
signal.connect(boost::bind([] {
printf("Fired!");
}, &test));
Which would NOT call the lambda after test is torn down.
2-- I do not want to directly manage the connection objects returned by .connect.
As can be seen here: "Use of the trackable class is not recommended for new code"
Perhaps choose to go with scoped_connection or track instead.
Example:
#include <iostream>
#include <memory>
#include <boost/signals2.hpp>
struct short_lived : public boost::signals2::scoped_connection {
public:
short_lived(const boost::signals2::connection &conn) : boost::signals2::scoped_connection{conn}
{ }
~short_lived() {
std::cout << "I'm dying...1!" << std::endl;
}
};
int main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
{
/* boost::signals2::scoped_connection */ short_lived conn{s1.connect([]() {
std::cout << "Fire1!" << std::endl;
})};
s1();
}
s1();
std::cout << std::endl;
{
auto lam = []() {
std::cout << "Fire2!" << std::endl;
};
/* shared_ptr with custom deleter that does not delete (since we didn't use new),
but prints a message */
std::shared_ptr<decltype(lam)> sptr{&lam, [](decltype(lam) *) { std::cout << "I'm dying...2!" << std::endl; }};
s1.connect(sig_type::slot_type(lam).track_foreign(sptr));
s1();
}
s1();
return 0;
}
http://melpon.org/wandbox/permlink/c8LHGIp8ArkKsnWA
Found the answer referencing trackable_test.cpp:
struct short_lived : public boost::signals2::trackable {
~short_lived() {
cout << "I'm dying...!" << std::endl;
}
};
void main() {
typedef boost::signals2::signal<void()> sig_type;
sig_type s1;
short_lived* shorty = new short_lived();
s1.connect(boost::bind<void>([](const short_lived*) {
cout << "Fire!" << std::endl;
}, shorty));
s1();
delete shorty;
s1();
}
Output
Fire!
I'm dying...!
...and a multiple params example (boost::bind refresher):
typedef boost::signals2::signal<void(int)> sig_type;
// ...same...
s1.connect(boost::bind<void>([](const short_lived*, int cannon) {
cout << "Fire " << cannon << "!" << std::endl;
}, shorty, _1));
s(1);
delete shorty;
s(2);
Output
Fire 1!
I'm dying...!
You can code something similar using shared/weak pointers:
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <iostream>
class Foo : public boost::signals2::trackable {
public:
void bar() {
printf("Fire!\n");
}
};
int main() {
boost::signals2::signal<void()> signal;
{
auto test = boost::make_shared<Foo>();
signal.connect([wp = boost::weak_ptr<Foo>(test)]
{
if (auto sp = wp.lock())
sp->bar();
else
std::cout << "expired\n";
}
);
signal();
}
signal();
}
Prints
Fire!
expired
The strictly c++11 version: Live On Coliru
Related
#include <iostream>
#include <string.h>
#include "Date.h"
#include "Employee.h"
using std::cout;
using std::endl;
using std::to_string;
class TestOps {
public:
int sex = 1;
string toString() {
return " sex:" + to_string(sex) ;
}
};
class Test {
public:
TestOps* testOps;
Test(const Test& t) :Test{} {
this->testOps = new TestOps{ *(t.testOps) };
};
Test() {
TestOps ops;
//this->testOps = new TestOps{}; // it will be ok with this way
this->testOps = &ops;
}
};
int main() {
// code not understand
Test t1;
cout <<"first testOps:" << t1.testOps->toString() << endl; // sex: 1
Test t2{ t1 };
cout << "first testOps:" << t1.testOps->toString() << endl; // sex: -858893460 ???? why?
cout << "second testOps:" << t2.testOps->toString() << endl; // sex: -858893460 ???? why?
return 0;
}
As you can see, why the first log is as expected while the later logs are not?
Also, t1.testOps address is different from t2.testOps which is as expected.
I have done some research but didn't find the answer. Maybe because I'm pretty new to cpp.
I'm trying to implement a custom vtable to better understand a concept of virtual tables and overriding. For this I have the following 'base' class
#pragma once
#include <iostream>
#include <string>
using namespace std::string_view_literals;
struct vtable;
class IdentityDocument {
public:
IdentityDocument()
: vtable_ptr_(&IdentityDocument::VTABLE),
unique_id_(++unique_id_count_)
{
std::cout << "IdentityDocument::Ctor() : "sv << unique_id_ << std::endl;
}
~IdentityDocument() {
--unique_id_count_;
std::cout << "IdentityDocument::Dtor() : "sv << unique_id_ << std::endl;
}
IdentityDocument(const IdentityDocument& other)
: vtable_ptr_(other.vtable_ptr_),
unique_id_(++unique_id_count_)
{
std::cout << "IdentityDocument::CCtor() : "sv << unique_id_ << std::endl;
}
IdentityDocument& operator=(const IdentityDocument&) = delete;
void PrintID() const {
std::cout << "IdentityDocument::PrintID() : "sv << unique_id_ << std::endl;
}
static void PrintUniqueIDCount() {
std::cout << "unique_id_count_ : "sv << unique_id_count_ << std::endl;
}
int GetID() const {
return unique_id_;
}
private:
vtable* vtable_ptr_ = nullptr;
static int unique_id_count_;
static vtable VTABLE;
int unique_id_;
};
struct vtable
{
void (IdentityDocument::* const PrintID)() const;
vtable (
void (IdentityDocument::* const PrintID)() const
) : PrintID(PrintID) {}
};
int IdentityDocument::unique_id_count_ = 0;
vtable IdentityDocument::VTABLE = {&IdentityDocument::PrintID};
And here is another class that must override PrintId method
#pragma once
#include "identity_document.h"
#include <iostream>
#include <string>
#include <ctime>
using namespace std::string_view_literals;
class Passport {
public:
Passport()
: expiration_date_(GetExpirationDate())
{
IdentityDocument* base_ptr = reinterpret_cast<IdentityDocument*>(this);
vtable* vtable_ptr = reinterpret_cast<vtable*>(base_ptr);
vtable_ptr = &Passport::VTABLE;
std::cout << "Passport::Ctor()"sv << std::endl;
}
Passport(const Passport& other)
: identity_(other.identity_)
, expiration_date_(other.expiration_date_)
{
IdentityDocument* base_ptr = reinterpret_cast<IdentityDocument*>(this);
vtable* vtable_ptr = reinterpret_cast<vtable*>(base_ptr);
vtable_ptr = &Passport::VTABLE;
std::cout << "Passport::CCtor()"sv << std::endl;
}
~Passport() {
std::cout << "Passport::Dtor()"sv << std::endl;
}
void PrintID() const {
std::cout << "Passport::PrintID() : "sv << identity_.GetID();
std::cout << " expiration date : "sv << expiration_date_.tm_mday << "/"sv << expiration_date_.tm_mon << "/"sv
<< expiration_date_.tm_year + 1900 << std::endl;
}
void PrintVisa(const std::string& country) const {
std::cout << "Passport::PrintVisa("sv << country << ") : "sv << identity_.GetID() << std::endl;
}
private:
IdentityDocument identity_;
const struct tm expiration_date_;
static vtable VTABLE;
tm GetExpirationDate() {
time_t t = time(nullptr);
tm exp_date = *localtime(&t);
exp_date.tm_year += 10;
mktime(&exp_date);
return exp_date;
}
};
vtable Passport::VTABLE = {reinterpret_cast<void (IdentityDocument::*)() const>(&Passport::PrintID)};
And a short demo :
int main() {
array<IdentityDocument*, 1> docs = { (IdentityDocument*)(new Passport()) };
for (const auto* doc : docs) {
doc->PrintID();
}
}
Unfortunately, I see that the 'derived' method was not called. Am I using a wrong approach to implement a vtable concept?
Am I using a wrong approach to implement a vtable concept?
Yes. You have not written any code that reads your vtable, and the C++ compiler will not generate any code to read your vtable either.
When you declare a member function virtual, your compiler needs to call that function in a special way. Any call to that function should be looked up in a vtable.
When a member function is not virtual, your compiler knows that it doesn't need to look up the location of the function. It knows which function to call. No lookup needed.
In your code, you have created a vtable, but this line, calling a non-virtual function:
doc->PrintID();
Does not need a vtable, and does not check for one.
doc is an IdentityDocument*, so doc->PrintID() calls IdentityDocument::PrintID(). No lookup required, no lookup happens.
Finally I simplified my solution and got what I wanted :
#include <iostream>
class A;
struct VTable
{
void (*say_hello)(A*);
};
class A
{
public:
A()
{
vtable.say_hello = A::sayHello;
}
void sayHello()
{
vtable.say_hello(this);
}
static void sayHello(A* a)
{
std::cout << "A::sayHello" << std::endl;
}
VTable vtable;
};
class B
{
public:
B()
{
a.vtable.say_hello = B::sayHello;
}
void sayHello()
{
a.vtable.say_hello((A*)this);
}
static void sayHello(A* a)
{
std::cout << "B::sayHello\n" << std::endl;
}
private:
A a;
};
int main()
{
A* a = (A*)(new B);
a->sayHello();
delete a;
}
I want to defer the construction of my member variable until the constructor's body and I am trying to use union to do that. Until now, it's achieving what I want but I want to ask is there any reason I shouldn't do this?
Example:
#include <iostream>
struct A {
A() {
std::cout << "Construct A" << std::endl;
}
~A() {
std::cout << "Destruct A" << std::endl;
}
};
struct B {
A a;
};
template <typename T>
union U {
char a{};
T buffer;
U() {}
~U() {
buffer.~T();
}
};
struct C {
U<B> u;
C() {
try {
new (&u.buffer) B();
} catch (...) {
}
}
};
Edit: Add sample usage
One of the reason you should not use the work around is that it does not make sense.
Apply try-catch on hole constructor will work well.
struct C {
A a;
C() try {
} catch (...) {
}
};
std::optional seems to be a great way to do this if you're at C++17.
#include <iostream>
#include <optional>
#include <stdexcept>
struct A {
A(bool fail = false) {
std::cout << "Attempting to construct A" << std::endl;
if (fail) {
throw std::runtime_error("Failed to construct A");
}
else {
std::cout << "Succeeded in constructing A" << std::endl;
}
}
~A() {
std::cout << "Destruct A" << std::endl;
}
};
struct B {
std::optional<A> a;
B(bool fail = false) {
try {
a.emplace(fail);
}
catch (std::runtime_error& ex) {
// fall back to a safe construction
std::cout << "Falling back to safe A construction" << std::endl;
a.emplace();
}
}
};
int main() {
{
B b_good; // should be fine
}
{
B B_bad(true); // should catch the exception and fall back
}
}
output:
Attempting to construct A
Succeeded in constructing A
Destruct A
Attempting to construct A
Failed to construct A
An option that forgoes the size of std::optional is to have the unallocated buffer, but (for type safety) access it through a reference.
#include <iostream>
#include <optional>
#include <stdexcept>
struct A {
A(bool fail = false) {
std::cout << "Attempting to construct A" << std::endl;
if (fail) {
throw std::runtime_error("Failed to construct A");
}
else {
std::cout << "Succeeded in constructing A" << std::endl;
}
}
~A() {
std::cout << "Destruct A" << std::endl;
}
};
struct B {
char a_buff_[sizeof(A)];
A& a_;
B(bool fail = false) : a_(*reinterpret_cast<A*>(a_buff_)) {
try {
new (&a_) A(fail);
}
catch (std::runtime_error& ex) {
std::cout << ex.what() << std::endl;
std::cout << "Falling back to safe A construction" << std::endl;
new (&a_) A();
}
}
~B() { a_.~A(); }
B(const B& other) : a_(other.a_) {}
B& operator=(const B& other) {
a_ = other.a_;
}
};
int main() {
{
B b_good; // should be fine
}
{
B b_bad(true); // should catch the exception and fall back
}
}
Attempting to construct A
Succeeded in constructing A
Destruct A
Attempting to construct A
Failed to construct A
Falling back to safe A construction
Attempting to construct A
Succeeded in constructing A
Destruct A
I got this:
class Core
{
protected:
static unsigned int id_seed;
unsigned int id;
std::string status;
public:
friend class CPU;
Core();
~Core();
virtual void procesare(std::string aplicatie) = 0;
};
class CoreScreen: public Core
{
public:
CoreScreen();
~CoreScreen();
void procesare(std::string aplicatie);
};
and corescreen.cpp:
#include "CoreScreen.h"
CoreScreen::CoreScreen()
{
}
CoreScreen::~CoreScreen()
{
}
void CoreScreen::procesare(std::string aplicatie)
{
std::string buffer;
std::ifstream file_in(aplicatie);
if (file_in.is_open()) {
std::cout << "Aplicatia " << aplicatie << " ruleaza: " << std::endl;
while (getline(file_in, buffer)) {
std::cout << buffer;
}
file_in.close();
}
else {
throw new CExceptie(APP_FAIL, " Aplicatia nu a putut rula!");
}
}
When I use in main:
CoreScreen CS1, CS2, CS3, CS4;
I get this error: 'Core' cannot instantiate abstract class.
What's the problem? I thought I have my virtual function declared in CoreScreen correctly.
As I presume you know, "Core" is an abstract class, by virtue of the fact it has a pure virtual function: virtual void procesare(std::string aplicatie) = 0;.
I presume you also know that you can't instantiate an abstract class: hence your error.
The question is:
Why does the compiler think you're trying to instantiate an instance of "Core"?
Are you?
It looks like you're trying to instantiate four CoreScreen objects: CoreScreen CS1, CS2, CS3, CS4;. If so, that should be perfectly OK.
You're correct: procesare() is virtual ("pure virtual", as it happens). You've indeed overridden it correctly in CoreScreen.cpp: it DOESN'T look like that's the problem.
Q: Did you ever implement Core::Core() and Core::~Core() anywhere? If not, how did you even compile?
Q: Are you SURE you're not trying to create an instance of "Core" anywhere (even "accidentally")?
For whatever it's worth, the following MCVE compiles and runs fine (Ubuntu 18, GCC 7.3.0):
TestCore.h:
/*
* TestCore.h
*/
#ifndef TESTCORE_H_
#define TESTCORE_H_
#include <string>
class Core
{
protected:
static unsigned int id_seed;
unsigned int id;
std::string status;
public:
friend class CPU;
Core();
~Core();
virtual void procesare(std::string aplicatie) = 0;
};
class CoreScreen: public Core
{
public:
CoreScreen();
~CoreScreen();
void procesare(std::string aplicatie);
};
#endif /* TESTCORE_H_ */
TestCore.cpp:
/*
* TestCore.cpp
*/
#include <iostream>
#include <fstream>
#include "TestCore.h"
Core::Core()
{
std::cout << "Core::Core()..." << std::endl;
}
Core::~Core()
{
std::cout << "Core::~Core()..." << std::endl;
}
CoreScreen::CoreScreen()
{
std::cout << "CoreScreen::CoreScreen()..." << std::endl;
}
CoreScreen::~CoreScreen()
{
std::cout << "CoreScreen::~CoreScreen()..." << std::endl;
}
void CoreScreen::procesare(std::string aplicatie)
{
std::cout << "CoreScreen::procesare(" << aplicatie << ")" << std::endl;;
}
int main () {
std::cout << ">>main()..." << std::endl;
CoreScreen CS1, CS2, CS3, CS4;
CS1.procesare("Testing CS1");
std::cout << "<<main()." << std::endl;
return 0;
}
SAMPLE OUTPUT:
>>main()...
Core::Core()...
CoreScreen::CoreScreen()...
Core::Core()...
CoreScreen::CoreScreen()...
Core::Core()...
CoreScreen::CoreScreen()...
Core::Core()...
CoreScreen::CoreScreen()...
CoreScreen::procesare(Testing CS1)
<<main().
You'll note that I implemented Core::Core() and Core::~Core(). If you don't need them - then don't even put them in your .h class definition.
'Hope that helps
I have a simple piece of code (Checker) which carries out some consistency checks on the elements of a vector (pps)
try{
const Checker& results = std::for_each(pps.begin(), pps.end(), Checker());
!results.diagnostic();
}
catch(std::bad_alloc&){
cout << "the check operation failed: out of memory" << endl;
}
Checker has a member function (diagnostic) which outputs the results of this check.
The problem is: if for some reason (std::bad_alloc, for example) the check operation gets interrupted, i would like to have the already produced diagnostic available. Is it possible without recurring to a "substantial rewrite" allowing me to do something like:
Checker::Diagnostic diagnostic;
try{
std::for_each(pps.begin(), pps.end(), Checker(diagnostic));
}
catch(std::bad_alloc&){
cout << "the check operation failed: out of memory" << endl;
}
diagnostic.output();
This would look unnatural, since the return of std::for_each is intended for the exact purpose of being able to do such things, and the exceptional flow of control would dominate the look of the code.
I would prefer to use the class like this:
Checker checker;
checker.doCheck(pps);
checker.diagnostic();
Or:
const Checker checker(pps);
checker.diagnostic();
That way, you can hide the details of the check in doCheck() (first example) or in the constructor (second example).
For example:
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
using ImportantItems = std::vector<int>;
class Checker {
public:
Checker(const int criticalItem) : criticalItem(criticalItem) { }
void doCheck(const ImportantItems& items)
{
accumulatedSum = 0;
try {
std::for_each(
items.begin(), items.end(),
boost::bind(&Checker::performExtensiveCheckingOnAnItem, this, _1));
this->dataOk = true;
}
catch (const std::runtime_error& e) {
this->dataOk = false;
}
std::cout << "AddAccumulated sum: " << accumulatedSum << std::endl;
}
void diagnostic() const
{
if (this->dataOk) {
std::cout << "Everything was fine in last check" << std::endl;
}
else {
std::cout << "Serious problems encountered" << std::endl;
}
}
private:
void performExtensiveCheckingOnAnItem(const int anItem)
{
if (criticalItem == anItem) {
throw std::runtime_error("Critical situation");
}
accumulatedSum += anItem;
}
const int criticalItem;
int accumulatedSum{};
bool dataOk{false};
};
int main()
{
const int criticalItem(5);
const ImportantItems importantItems{1, 2, 3, 4/*, criticalItem*/};
Checker checker(criticalItem);
checker.doCheck(importantItems);
checker.diagnostic();
return 0;
}