I have class MyClass that can be modified by calling setX.
I want to know if an object of MyClass has been changed by calling isChanged.
In the code below, I don’t like to add setDirty or m_dataChanged in every method that can change the state of an object.
class ChangesHolder
{
private:
bool m_isChanged;
// boost::signals2::signal<void()> m_dataChanged;
// long m_stamps;
public:
ChangesHolder()
: m_isChanged{false}
// , m_stamps{0}
{
// m_dataChanged.connect(std::bind(&ChangesHolder::setDirty, this));
}
bool isChanged() const
{
return m_isChanged;
// return (m_stamps == 0);
}
void resetChanges()
{
m_isChanged = false;
// m_stamps = 0;
}
protected:
void setDirty()
{
m_isChanged = true;
// ++m_stamps;
}
}
class MyClass : public ChangesHolder
{
private:
int m_x;
public:
void setX(int x)
{
if (m_x != x)
{
m_x = x;
setDirty();
// m_dataChanged();
}
}
}
I want to register such methods like this:
template<typename ... Funcs>
void startTrack(Funcs ... funcs)
{
auto connect = [&](auto func)
{
// connect func to setDirty
};
do_foreach(connect, funcs ...);
}
MyClass::MyClass()
{
startTrack(&MyClass::setX, &MyClass::setY);
}
How can this be done or maybe there are other ways to do it?
Related
I am currently trying to learn c++ and I am having an issue when trying to create a vector which iterates through several different objects whom all inherit from the same base class with smart pointers.
I parse a file and create the objects and insert them into the vector depending on the character parsed but I keep getting the error:
Error C2664 'std::unique_ptr<Test *,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::unique_ptr<Test2,std::default_delete<_Ty>>' to 'std::nullptr_t'"
Code is as follows:
class Test {
public:
virtual ~Test(){}
virtual int update() {}
};
class Test2 : public Test {
private:
int a;
public:
Test2() {
}
Test2(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test3 : public Test {
private:
int a;
public:
Test3() {
}
Test3(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test4 : public Test {
private:
int a;
public:
Test4() {
}
Test4(int n) {
a = n;
}
int update() override {
return a;
}
};
class manager {
private:
std::vector<std::unique_ptr<Test*>> vList;
std::ifstream lvlFile;
public:
std::string tmp;
manager() {
}
~manager() {
}
void init(const char *path) {
lvlFile.open(path, 0);
while (lvlFile.eof() != true) {
std::getline(lvlFile, tmp);
for (char& a : tmp) {
switch (a) {
case 'w':
vList.emplace_back(std::make_unique<Test2>(2));
break;
case 'g':
vList.emplace_back(std::make_unique<Test3>(3));
break;
}
}
}
}
void print() {
for (auto& i : vList) {
std::cout << (*i)->update() << std::endl;
}
}
};
manager *m;
int main() {
m = new manager();
m->init("lvl.txt");
_getch();
}
Maybe I have misunderstood something crucial here but I have been looking around and found no real answers so any pointers to this would be most welcome!
Change std::vector<std::unique_ptr<Test*>> to std::vector<std::unique_ptr<Test>>.
std::unique_ptr<Test*> is a pointer to pointer (Test**).
I have a function that takes a long time to run, but thankfully it runs asynchronously. I want to take the result of this function call and set it to a class instance's private variable. Seems easy:
// Exists in some other library.
void LongRunningAsync(std::function<void(int)> callback) {
sleep(10);
callback(5);
}
class A {
public:
void Do() {
auto lambda = [this](int val) {
// Some processing...
var_ = val;
};
LongRunningAsync(lambda);
}
private:
var_;
};
int main() {
A* a = new A;
a->Do();
// Wait for LongRunningAsync to finish.
sleep(20);
return 0;
}
The problem is adding the following line to main, right before the comment:
delete a;
Now when LongRunningAsync invokes the callback, it will attempt to modify a member variable of a deleted instance (which is UB).
Is there a way to salvage this approach? I've recently learned about the following solution:
void LongRunningAsync(std::function<void(int)> callback) {
sleep(10);
callback(5);
}
class A : public std::enable_shared_from_this<A> {
public:
void Do() {
std::weak_ptr<A> weak = shared_from_this();
auto lambda = [weak](int val) {
auto shared = weak.lock();
if (!shared) return;
// Some processing...
shared->var_ = val;
};
LongRunningAsync(lambda);
}
private:
var_;
};
int main() {
auto a = std::make_shared<A>();
a->Do();
// Wait for LongRunningAsync to finish.
sleep(20);
return 0;
}
But it requires changing all A variables to shared_ptr. Is there a less intrusive way to make this work?
One possible solution is to just encapsulate the state you need into a shared_ptr member variable and then capture that by value into the closure that runs asynchronously.
Something like the following
class A : public std::enable_shared_from_this<A> {
public:
void Do() {
auto lambda = [member_shared_state](int val) {
member_shared_state->var_ = val;
};
LongRunningAsync(lambda);
}
....
};
Here's a solution based on Curious's approach, but that doesn't force me to change all pointers to A objects to shared_ptr:
// Exists in some other library.
void LongRunningAsync(std::function<void(int)> callback) {
sleep(10);
callback(5);
}
class A {
public:
A() : var_(std::make_shared<int>()) {}
void Do() {
std::weak_ptr<int> weak = var_;
auto lambda = [weak](int val) {
auto shared = weak.lock();
if (!shared) {
return;
}
// Some processing...
*shared = val;
};
LongRunningAsync(lambda);
}
private:
std::shared_ptr<int> var_;
};
int main() {
A* a = new A;
a->Do();
delete a;
// Wait for LongRunningAsync to finish.
sleep(20);
return 0;
}
RequestS want to use ReportUrlThread's function(send) .ReportUrlThread is a template class.
It look like below the code is that "request->process(reportUrl->send);",
how can I achieve it?
The codes below can't be through compilation.
int main()
{
typedef Threadpool<RequestS> ThreadpoolDealFromBS2;
ThreadpoolDealFromBS2 threadpool;
ReportUrlReq* req = new ReportUrlReq();
threadpool.appendReportHiUrl(req);
}
class RequestS {
public:
RequestS()
{
}
virtual ~RequestS()
{
}
virtual void process(void (*send)(bool &exp))
{
log(Info, "RequestS...fun");
}
};
class ReportUrlReq:public RequestS {
public:
ReportUrlReq();
~ReportUrlReq();
virtual void process(void (*send)(bool &exp))
{
log(Info, "ReportUrlReq...fun");
}
};
template< typename T >
class ReportUrlThread {
public:
ReportUrlThread(uint32_t id)
{
}
virtual ~ReportUrlThread()
{
}
void send(bool &exp)
{
}
Threadpool< T >* threadpool;
};
template< typename T >
class Threadpool
{
public:
Threadpool( std::vector<ReportUrlThread<T>*>& reportUrl);
~Threadpool();
bool appendReportHiUrl( T* request );
private:
static void* reportWorker( void* arg );
void reportRun(ReportUrlThread<T> *reportUrl);
pthread_t* m_ReportUrlThreads;
};
template< typename T >
Threadpool< T >::Threadpool( std::vector<ReportUrlThread<T>*>& reportUrl)
{
m_ReportUrlThreads = new pthread_t[reportUrlThreadNum];
for (int i = 0; i < 10; ++i)
{
ReportUrlThread<T> * reportUrlThread = reportUrl[i];
reportUrlThread->threadpool = this;
if( pthread_create( m_ReportUrlThreads + i, NULL, reportWorker, reportUrlThread ) != 0 )
{
delete [] m_ReportUrlThreads;
throw std::exception();
}
if( pthread_detach( m_ReportUrlThreads[i] ) )
{
delete [] m_ReportUrlThreads;
throw std::exception();
}
}
}
template< typename T >
void* Threadpool< T >::reportWorker( void* arg )
{
ReportUrlThread<T>* reportUrl = (ReportUrlThread<T>*)arg;
Threadpool* pool = reportUrl->threadpool;
pool->reportRun(reportUrl);
return pool;
}
template< typename T >
void Threadpool< T >::reportRun(ReportUrlThread<T> *reportUrl)
{
while ( ! m_ReportStop )
{
m_ReportQueuestat.wait();
m_ReportQueuelocker.lock();
if ( m_ReportWorkqueue.empty() )
{
m_ReportQueuelocker.unlock();
continue;
}
T* request = m_ReportWorkqueue.front();
m_ReportWorkqueue.pop_front();
reportDealNum++;
m_ReportWorkqueueSize = m_ReportWorkqueue.size();
request->process(reportUrl->send);
}
}
The actual error is, that you're passing the memberfunction reportUrl->send to request->process expecting an ordinary function. But a member function needs an instance of its class! If send depends on members of ReportUrlThread, you might want to pass an instance of ReportUrlThread (or a derived class implementing send):
virtual void process(ReportUrlThread<RequestS> *RepUrlThReqS) {
bool exp;
RepUrlThReqS->send(exp);
// ...
}
If not, you might want to use a static function:
static void send(bool &exp) {
// ...
}
You might even want to use a lambda function (which is quite a bit hacky here):
class RequestS {
public:
virtual void process(void(*send)(bool &exp, void* instance), void *instance) {
bool exp;
send(exp, instance);
}
};
template< typename T >
class ReportUrlThread {
public:
void send(bool &exp) { }
};
int main() {
ReportUrlThread<RequestS> *reportUrl = new ReportUrlThread<RequestS>;
RequestS *request = new RequestS;
request->process(
[](bool &exp, void* reportUrlA) {
((ReportUrlThread<RequestS> *)reportUrlA)->send(exp);
}, reportUrl);
}
And many more possibilities...
It's up to you to decide, which is the best solution in your case.
I have the following class:
class Timer
{
public:
Timer(){};
~Timer(){};
void timer(int);
//...
private:
//...
};
My function timer(int value) is a callback that I use in glutTimerFunc(), inside the function timer(int value) i need to use the function timer again, something like this:
void Timer::timer(int value)
{
//...
glutTimerFunc(state->getTimer(), this->timer, 0);
}
How can i do it without using a static function?
you'll need a global dispatcher that turns the int passed to glutTimerFunc into a c++ callback (member function, lambda, etc)
something like this
struct timer_dispatch
{
using callback_t = std::function<void()>;
int start_timer(int msecs, callback_t callback) {
std::unique_lock<std::mutex> lock(_mutex);
int ident = _next_id++;
_callbacks.emplace(ident, std::move(callback));
glutTimerFunc(msecs, &timer_dispatch::dispatch_timer, ident);
return ident;
}
// implement similar function for stop timer - don't forget the mutex
void stop_timer(int ident) {
std::unique_lock<std::mutex> lock(_mutex);
_callbacks.erase(ident);
}
static timer_dispatch& instance() {
static timer_dispatch _;
return _;
}
private:
// private constructor ensures use via the instance() static method;
timer_dispatch() = default;
static void dispatch_timer(int ident) {
auto self = instance();
std::unique_lock<std::mutex> lock(self._mutex);
auto it = self._callbacks.find(ident);
if (it != self._callbacks.end()) {
auto my_copy = std::move(it->second);
self._callbacks.erase(it);
lock.unlock();
my_copy();
}
}
private:
std::unordered_map<int, callback_t> _callbacks;
std::mutex _mutex;
int _next_id = 0;
};
now use like so:
// start my timer:
void myclass::start_alien() {
...
_alien_timer_id = timer_dispatch::instance().start_timer(100, std::bind(&myclass::on_alien_timeout, this);
...
}
void myclass::on_alien_timeout() {
// make alien do something, possibly restart a timer...
_alien_timer_id = timer_dispatch::instance().start_timer(100, std::bind(&myclass::on_alien_timeout, this);
}
void myclass::on_alien_killed() {
timer_dispatch::instance().stop_timer(_alien_timer_id);
_alien_timer_id = -1;
}
I realize that I'll most likely get a lot of "you shouldn't do that because..." answers and they are most welcome and I'll probably totally agree with your reasoning, but I'm curious as to whether this is possible (as I envision it).
Is it possible to define a type of dynamic/generic object in C++ where I can dynamically create properties that are stored and retrieved in a key/value type of system? Example:
MyType myObject;
std::string myStr("string1");
myObject.somethingIJustMadeUp = myStr;
Note that obviously, somethingIJustMadeUp is not actually a defined member of MyType but it would be defined dynamically. Then later I could do something like:
if(myObject.somethingIJustMadeUp != NULL);
or
if(myObject["somethingIJustMadeUp"]);
Believe me, I realize just how terrible this is, but I'm still curious as to whether it's possible and if it can be done in a way that minimizes it's terrible-ness.
C++Script is what you want!
Example:
#include <cppscript>
var script_main(var args)
{
var x = object();
x["abc"] = 10;
writeln(x["abc"]);
return 0;
}
and it's a valid C++.
You can do something very similar with std::map:
std::map<std::string, std::string> myObject;
myObject["somethingIJustMadeUp"] = myStr;
Now if you want generic value types, then you can use boost::any as:
std::map<std::string, boost::any> myObject;
myObject["somethingIJustMadeUp"] = myStr;
And you can also check if a value exists or not:
if(myObject.find ("somethingIJustMadeUp") != myObject.end())
std::cout << "Exists" << std::endl;
If you use boost::any, then you can know the actual type of value it holds, by calling .type() as:
if (myObject.find("Xyz") != myObject.end())
{
if(myObject["Xyz"].type() == typeid(std::string))
{
std::string value = boost::any_cast<std::string>(myObject["Xyz"]);
std::cout <<"Stored value is string = " << value << std::endl;
}
}
This also shows how you can use boost::any_cast to get the value stored in object of boost::any type.
This can be a solution, using RTTI polymorphism
#include <map>
#include <memory>
#include <iostream>
#include <stdexcept>
namespace dynamic
{
template<class T, class E>
T& enforce(T& z, const E& e)
{ if(!z) throw e; return z; }
template<class T, class E>
const T& enforce(const T& z, const E& e)
{ if(!z) throw e; return z; }
template<class Derived>
class interface;
class aggregate;
//polymorphic uncopyable unmovable
class property
{
public:
property() :pagg() {}
property(const property&) =delete;
property& operator=(const property&) =delete;
virtual ~property() {} //just make it polymorphic
template<class Interface>
operator Interface*() const
{
if(!pagg) return 0;
return *pagg; //let the aggregate do the magic!
}
aggregate* get_aggregate() const { return pagg; }
private:
template<class Derived>
friend class interface;
friend class aggregate;
static unsigned gen_id()
{
static unsigned x=0;
return enforce(++x,std::overflow_error("too many ids"));
}
template<class T>
static unsigned id_of()
{ static unsigned z = gen_id(); return z; }
aggregate* pagg;
};
template<class Derived>
class interface: public property
{
public:
interface() {}
virtual ~interface() {}
unsigned id() const { return property::id_of<Derived>(); }
};
//sealed movable
class aggregate
{
public:
aggregate() {}
aggregate(const aggregate&) = delete;
aggregate& operator=(const aggregate&) = delete;
aggregate(aggregate&& s) :m(std::move(s.m)) {}
aggregate& operator=(aggregate&& s)
{ if(this!=&s) { m.clear(); std::swap(m, s.m); } return *this; }
template<class Interface>
aggregate& add_interface(interface<Interface>* pi)
{
m[pi->id()] = std::unique_ptr<property>(pi);
static_cast<property*>(pi)->pagg = this;
return *this;
}
template<class Inteface>
aggregate& remove_interface()
{ m.erase[property::id_of<Inteface>()]; return *this; }
void clear() { m.clear(); }
bool empty() const { return m.empty(); }
explicit operator bool() const { return empty(); }
template<class Interface>
operator Interface*() const
{
auto i = m.find(property::id_of<Interface>());
if(i==m.end()) return nullptr;
return dynamic_cast<Interface*>(i->second.get());
}
template<class Interface>
friend aggregate& operator<<(aggregate& s, interface<Interface>* pi)
{ return s.add_interface(pi); }
private:
typedef std::map<unsigned, std::unique_ptr<property> > map_t;
map_t m;
};
}
/// this is a sample on how it can workout
class interface_A: public dynamic::interface<interface_A>
{
public:
virtual void methodA1() =0;
virtual void methodA2() =0;
};
class impl_A1: public interface_A
{
public:
impl_A1() { std::cout<<"creating impl_A1["<<this<<"]"<<std::endl; }
virtual ~impl_A1() { std::cout<<"deleting impl_A1["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_A2: public interface_A
{
public:
impl_A2() { std::cout<<"creating impl_A2["<<this<<"]"<<std::endl; }
virtual ~impl_A2() { std::cout<<"deleting impl_A2["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
};
class interface_B: public dynamic::interface<interface_B>
{
public:
virtual void methodB1() =0;
virtual void methodB2() =0;
};
class impl_B1: public interface_B
{
public:
impl_B1() { std::cout<<"creating impl_B1["<<this<<"]"<<std::endl; }
virtual ~impl_B1() { std::cout<<"deleting impl_B1["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_B2: public interface_B
{
public:
impl_B2() { std::cout<<"creating impl_B2["<<this<<"]"<<std::endl; }
virtual ~impl_B2() { std::cout<<"deleting impl_B2["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
};
int main()
{
dynamic::aggregate agg1;
agg1 << new impl_A1 << new impl_B1;
dynamic::aggregate agg2;
agg2 << new impl_A2 << new impl_B2;
interface_A* pa = 0;
interface_B* pb = 0;
pa = agg1; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
agg2 = std::move(agg1);
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
return 0;
}
tested with MINGW4.6 on WinXPsp3
Yes it is terrible. :D
It had been done numerous times to different extents and success levels.
QT has Qobject from which everything related to them decends.
MFC has CObject from which eveything decends as does C++.net
I don't know if there is a way to make it less bad, I guess if you avoid multiple inheritance like the plague (which is otherwise a useful language feature) and reimplement the stdlib it would be better. But really if that is what you are after you are probably using the wrong language for the task.
Java and C# are much better suited to this style of programming.
#note if I have read your question wrong just delete this answer.
Check out Dynamic C++