I'm trying to refactor some code by facotirising duplicate code.
Let's imagine I end up with a class like:
class A {
public:
void method1()
{
do_work(true);
}
void method2() const
{
do_work(false);
}
private:
void do_work(bool flag) {
...
if(flag)
this->data = 0;
}
}
However this won't compile because do_work is not const, even though calling this method with flag = false is const.
Is there a way to "fix" this without splitting again the implementations?
do_work is poorly refactored, as a function that is "sometimes const".
Separate out the const and non-const logic.
class A {
void method1()
{
do_work();
this->data = 0;
}
void method2() const
{
do_work();
}
private:
void do_work() const {
...
}
}
Related
I'm working on an arduino project, this is relevant since there's no support for STL nor dynamic allocation on arduino natively. I've noticed that a lot of classes I'm writing do nothing on construction, but have an .init() method that actually initializes any resources. This is because that way the class can be initialized in the global scope, and then when the setup function runs, actual initialization happens as .init() is called there.
For example:
const portn_t en=A5, rs=A4, d4=A0, d5=A1, d6=A2, d7=A3;
// making room for that object in the global scope
// this way it can be both used in ``setup()`` and ``loop()``
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
lcd.begin(16, 2); // Doing the actual initialization
}
void loop() {
lcd.clear();
lcd.write("Hello world!");
delay(500);
}
This works fine for classes that are designed with an init or begin method. This design pattern is common in most Arduino libraries, but for classes that don't implement this I'm currently using this as a workaround:
Button& get_btn_up() {
// The Button class actually does initialization at construcion
static Button bt(2, true);
return bt;
}
Button& get_btn_enter() {
static Button bt(3, true);
return bt;
}
Button& get_btn_down() {
static Button bt(4, true);
return bt;
}
void setup() {
// Initializes all the ``Button`` objects
get_btn_up();
get_btn_enter();
get_btn_down();
}
void loop() {
auto up = get_btn_up();
if (up.just_pressed()) {
...
}
...
}
Which I don't believe is an optimal solution, as there's a lot of boiler plate just to achieve something that could be done with new and some unique pointers.
Because of this I attempted making a DelayedInit container class, that would hold the required memory for the object in a union and handle its lifetime
template<typename T>
union MemoryOf {
uint8_t memory [sizeof(T)];
T obj;
};
template<typename T>
struct DelayedInit {
private:
MemoryOf<T> memory{.memory={ 0 }};
bool is_set = false;
public:
T& get() const {
memory.obj;
}
DelayedInit() {}
~DelayedInit() {
if (is_set)
get().~T();
}
T* operator->() const {
return &get();
}
T& operator*() {
is_set = true;
return get();
}
const T& operator*() const {
return get();
}
explicit operator bool() const {
return is_set;
}
};
This implementation is broken at the time, as it locks the arduino up whenever I try to call any methods of the boxed class. Here's how it's supposed to be used
DelayedInit<Button> up, enter, down;
void setup() {
*up = Button(2, true);
*enter= Button(3, true);
*down = Button(4, true);
}
void loop() {
if (up->just_pressed()) { // Locks up the arduino
...
}
...
}
I'm guessing there's some memory management error in the code that I'm not aware of. What errors are present in the DelayedInit implementation? Is there a better approach at solving this issue?
This is the solution I ended up with. .init emulates the pattern that most classes in the arduino libraries use, without actually splitting the init logic in two methods. There's definitely room for improvement, but this works for global variables.
#pragma once
#include <new>
template<typename T>
union MemoryOf {
uint8_t memory [sizeof(T)];
T obj;
MemoryOf() : memory{ 0 } {};
~MemoryOf() {};
};
// Only tested with global variables
// so there might be bugs in the cleanup bits
template<typename T>
struct DelayedInit {
private:
MemoryOf<T> memory;
bool is_set = false;
public:
const T& get() const {
return memory.obj;
}
T& get() {
return memory.obj;
}
void remove() {
get().~T();
}
DelayedInit() {};
~DelayedInit() {
if (is_set)
remove();
}
template<typename ...Args>
inline void init(Args ...args) {
if (is_set) {
remove();
}
new (&memory.memory) T(args...); // == &memory.obj
is_set = true;
}
T* operator->() {
return &get();
}
const T* operator->() const {
return &get();
}
T& operator*() {
return get();
}
const T& operator*() const {
return get();
}
explicit operator bool() const {
return is_set;
}
};
Usage:
#include "delayed_init.hpp"
DelayedInit<Button> up, enter, down;
void setup() {
up.init(2, true);
enter.init(3, true);
down.init(4, true);
}
void loop() {
if (up->just_pressed()) {
...
}
...
}
Thanks to EOF for suggesting the use of placement new!
new Widget by two smart Pointer manager,so there will be a double free of problems, but does not appear after execution
std::vector<std::shared_ptr<Widget>> processedWidget;
class Widget {
public:
void process();
};
void Widget::process() {
processedWidget.emplace_back(this);
}
int main() {
{
std::shared_ptr<Widget> w(new Widget);
w->process();
}
return 0;
}
Double delete is undefined behavior by the standard. So it may appear to work, while hiding a disaster. The correct approach for code like this is to use std::enable_shared_from_this
std::vector<std::shared_ptr<Widget>> processedWidget;
class Widget : private std::enable_shared_from_this<Widget> {
public:
void process();
};
void Widget::process() {
processedWidget.emplace_back(shared_from_this());
}
int main() {
{
std::shared_ptr<Widget> w(new Widget);
w->process();
}
return 0;
}
I am writing callbacks system. I would to have something like that:
void someFunction(int, int);
void otherFunction(int, bool, std::string);
CallbackFunc *callback1 = new CallbackFunc( someFunction );
CallbackFunc *callback2 = new CallbackFunc( otherFunction );
callback1-> call(2, 6);
callback1-> call(1024, 456);
callback2-> call(-33, true, "Hello world");
My classes should can call each given function: don't know parameters count and their types.
I was trying that:
class Callback {
public:
virtual void call(...) = 0;
};
class CallbackFunc: public Callback {
protected:
void (*m_proc)(...);
public:
CallbackFunc(void (*proc) (...)) {
this-> m_proc = proc;
}
void call (...) {
this-> m_proc(<arguments given to call>);
}
};
But it doesn't work. I have second idea:
template<typename ArgType>
class Arg {
protected:
ArgType va;
public:
Arg() {
}
Arg(ArgType v) {
this->va = v;
}
ArgType get() {
return this->va;
}
void operator =(ArgType v) {
this->va = v;
}
};
class Callback {
public:
virtual void call(Arg, ...) = 0;
};
class CallbackFunc: public Callback {
protected:
void (*m_proc)(Arg ...);
public:
CallbackFunc(void (*proc) (Arg ...)) {
this-> m_proc = proc;
}
void call (Arg arg...) {
va_list args;
va_start(args, arg);
this-> m_proc(args);
va_end(args);
}
};
Still errors. Is it possible to make this way? I want to make usable code - user shouldn't know if CallbackFunc uses templates. I can't use void* and boost. C++ 2011 is not supported completely by some compilers I use, so that I can't use this standard too.
Currently I have two functions:
void foo(const A & a) {
...
result = ...
result += handle(a); // 1
bar(result);
}
void foo() {
...
result = ...
bar(result);
}
All code in foo() are the same except 1.
Can I merge them to one function like following?
void foo(const A & a = 0) {
...
...
if (a) result += handle(a); // this won't work, but can I do something similar?
bar(result);
}
Btw, the parameter has to be a reference as I would like to keep the interface unchanged.
You can use the Null Object Pattern.
namespace
{
const A NULL_A; // (possibly "extern")
}
void foo(const A & a = NULL_A) {
...
result = ...
if (&a != &NULL_A) result += handle(a);
bar(result);
}
No. A reference is always an alias for a real object (assuming you don't trigger undefined behavior). You can achieve similar behavior without code duplication by accepting a pointer instead:
void foo_impl(A const* obj) {
// code as before, except access obj with -> rather than .
}
void foo (A const& obj) {
foo_impl(&obj);
}
void foo() {
foo_impl(nullptr);
}
In the spirit of DRY, why not merge them as such?
void foo(const A & a) {
foo();
handle(a);
}
void foo() {
...
...
}
The entire idea of using reference is that you avoid the NULL pointer issue. The reference nothing but an alias for the real object. I have an another simple idea for your program, basically you want to achieve two functionality with same function - using default parameters. Here is the code. Please excuse me for the variable names.
class ABC
{
public:
int t;
ABC operator=(ABC& other)
{
other.t = 0;
}
};
ABC other;
void foo( ABC &a=other);
void foo( ABC &a)
{
if( a.t == 0)
qDebug()<<"The A WAS ZERO";
else
qDebug()<<"THE A isn't zero";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ABC hello;
hello.t = 100;
foo();
foo(hello);
return a.exec();
}
Here is the output.
The A WAS ZERO
THE A isn't zero
Use a base class that provides an interface, and two derived classes that implement the interface, one using A and the other using nothing.
Refactor foo to use a common foo.
struct Handler
{
virtual int get() = 0;
};
struct AHandler : Handler
{
AHandler(const A& a) : a_(a) {}
virtual int get() { return handle(a_); }
const A& a_;
}
struct NullHandler : Handler
{
virtual int get() { return 0; }
}
void foo(const Handler & h) {
...
result = ...
result += h.get();
bar(result);
}
void foo(const A & a) {
AHandler ah(a);
foo(ah);
}
void foo() {
NullHandler nh(a);
foo(nh);
}
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++