#include <iostream>
int main()
{
std::cout << "Hi, I'm Borislav!\n";
std::cout << "These slides are here: https://is.gd/bbb2cpp\n";
return 0;
}
#include <iostream>
int main()
{
std::cout << "Hi, I'm Borislav!\n";
std::cout << "These slides are here: https://is.gd/bbb2cpp\n";
return 0;
}
A part of a program which deals with the real world rules that determine how data is obtained, stored and processed.
The part which deals with the software's purpose
int a;
int b;
cin >> a >> b;
cout << a + b << '\n';
Business logic: adding two integers
The part which deals with the software's purpose
int a;
int b;
cin >> a >> b;
cout << a + b << '\n';
Business logic: adding two integers
The part which deals with the software's purpose
FirstInteger a;
SecondInteger b;
input.obtainValues(a, b);
gui.display(a + b);
Business logic: adding two integers
The part which deals with the software's purpose
FirstInteger a;
SecondInteger b;
input.obtainValues(a, b);
gui.display(a + b);
Business logic: adding two integers
Presentation, i/o...
FirstInteger a;
SecondInteger b;
input.obtainValues(a, b);
gui.display(a + b);
Non-business logic
Complex software doesn't mean complex business logic.
_
Simple. Right?
People don't seem to want to write business logic in C++
Note that there still is a lot of underlying C++ in such projects
Well... is there a problem with that?
Why don't people use C++?
Controversial. I know
People forget that C++ is an OOP language
But most importantly...
Software is written by human beings
Human beings think in terms of objects
Which languages thrive in fields with heavy business logic?
Almost all are object-oriented ones.
function f(shape) {
// Everything that has a draw method works
shape.draw();
}
Square = function () {
this.draw = function() {
console.log("Square");
}
};
Circle = function () {
this.draw = function() {
console.log("Circle");
}
};
f(new Square);
f(new Circle);
struct Shape {
virtual void draw(ostream& out) const = 0;
}
void f(const Shape& s) {
s.draw(cout);
}
struct Square : public Shape {
virtual void draw(ostream& out) const override { out << "Square\n"; }
};
struct Circle : public Shape {
virtual void draw(ostream& out) const override { out << "Circle\n"; }
};
int main() {
f(Square{});
f(Circle{});
}
However C++ is a pretty powerful language.
Boost.TypeErasure, Dyno, Folly.Poly, [Boost].TE
using Shape = Library_Magic(void, draw, (ostream&));
void f(const Shape& s) {
s.draw(cout);
}
struct Square {
void draw(ostream& out) const { out << "Square\n"; }
};
struct Circle {
void draw(ostream& out) const { out << "Circle\n"; }
};
int main() {
f(Square{});
f(Circle{});
}
Boost.TypeErasure, Dyno, Folly.Poly, [Boost].TE
using Shape = Library_Magic(void, draw, (ostream&));
void f(const Shape& s) {
s.draw(cout);
}
struct Square {
void draw(ostream& out) const { out << "Square\n"; }
};
struct Circle {
void draw(ostream& out) const { out << "Circle\n"; }
};
int main() {
f(Square{});
f(Circle{});
}
Square.ptototype.area = function() {
return this.side * this.side;
}
Circle.ptototype.area = function() {
return this.radius * this.radius * Math.PI;
}
s = new Square;
s.side = 5;
console.log(s.area()); // 25
struct Shape {
virtual void draw(ostream& out) const = 0;
}
struct Square : public Shape {
virtual void draw(ostream& out) const override { out << "Square\n"; }
int side;
};
int main()
{
shared_ptr<Shape> ptr = make_shared<Square>();
cout << ptr->area() << '\n'; // ??
}
struct Shape {
virtual void draw(ostream& out) const = 0;
virtual double area() const = 0;
}
struct Square : public Shape {
virtual void draw(ostream& out) const override { out << "Square\n"; }
virtual double area() const override { return side * side; }
double side;
};
int main()
{
shared_ptr<Shape> ptr = make_shared<Square>();
cout << ptr->area() << '\n';
}
And what if we can't just edit the classes?
Not to be confused with extension methods or UCS
declare_method(double, area, (virtual_<const Shape&> s);
define_method(double, area, (const Square& s)
{
return s.area * s.area;
}
int main() {
shared_ptr<Shape> ptr = make_shared<Square>();
cout << area(ptr) << '\n';
}
Not to be confused with extension methods or UCS
declare_method(double, area, (virtual_<const Shape&> s);
define_method(double, area, (const Square& s)
{
return s.area * s.area;
}
int main() {
shared_ptr<Shape> ptr = make_shared<Square>();
cout << area(ptr) << '\n';
}
multi sub collide(Square $s, Square $c) {
collide_square_square($s, $c);
}
multi sub collide(Circle $s, Circle $c) {
collide_circle_circle($s, $c);
}
multi sub collide(Square $s, Circle $c) {
collide_square_circle($s, $c);
}
multi sub collide(Circle $c, Square $s) {
collide_square_circle($s, $c);
}
my $s1 = get_random_shape;
my $s2 = get_random_shape;
say "Collision: " ~ collide($s1, $s2);
struct Shape {
virtual bool collide(const Shape* other) const = 0;
virtual bool collideImpl(const Square*) const = 0;
virtual bool collideImpl(const Circle*) const = 0;
virtual bool collideImpl(const Triangle*) const = 0;
}
struct Square : public Shape {
virtual bool collide(const Shape* other) const override {
return other->collideImpl(this);
}
virtual bool collideImpl(const Square*) const override;
virtual bool collideImpl(const Circle*) const override;
virtual bool collideImpl(const Triangle*) const override;
};
// ...
shared_ptr<Shape> s1 = get_random_shape();
shared_ptr<Shape> s2 = get_random_shape();
cout << "Collision: " << s1->collide(s2.get()) << '\n';
struct Shape {
virtual bool collide(const Shape* other) const = 0;
virtual bool collideImpl(const Square*) const = 0;
virtual bool collideImpl(const Circle*) const = 0;
virtual bool collideImpl(const Triangle*) const = 0;
}
struct Square : public Shape {
virtual bool collide(const Shape* other) const override {
return other->collideImpl(this); /* copy this in every shape */
}
virtual bool collideImpl(const Square*) const override;
virtual bool collideImpl(const Circle*) const override;
virtual bool collideImpl(const Triangle*) const override;
};
// ...
shared_ptr<Shape> s1 = get_random_shape();
shared_ptr<Shape> s2 = get_random_shape();
cout << "Collision: " << s1->collide(s2.get()) << '\n';
struct Shape {
virtual bool collide(const Shape* other) const = 0;
virtual bool collideImpl(const Square*) const = 0;
virtual bool collideImpl(const Circle*) const = 0;
virtual bool collideImpl(const Triangle*) const = 0;
}
struct Square : public Shape {
virtual bool collide(const Shape* other) const override {
return other->collideImpl(this);
}
virtual bool collideImpl(const Square*) const override;
virtual bool collideImpl(const Circle*) const override;
virtual bool collideImpl(const Triangle*) const override;
};
// ...
shared_ptr<Shape> s1 = get_random_shape();
shared_ptr<Shape> s2 = get_random_shape();
cout << "Collision: " << s1->collide(s2.get()) << '\n';
declare_method(bool, collide,
(virtual_<const Shape&> s1, (virtual_<const Shape&> s2));
define_method(bool, collide, (const Square& s, const Circle& c)
{
return collide_square_circle(s, c);
}
define_method(bool, collide, (const Circle& c, const Square& s)
{
return collide_square_circle(s, c);
}
// ...
shared_ptr<Shape> s1 = get_random_shape();
shared_ptr<Shape> s2 = get_random_shape();
cout << "Collision: " << collide(*s1, *s2) << '\n';
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
module FlyingCreature
def move_to(target)
puts can_move_to?(target) ?
"flying to #{target}"
: "can't fly to #{target}"
end
def can_move_to?(target)
true # flying creatures don't care
end
end
module AfraidOfEvens
def can_move_to?(target)
target % 2 != 0
end
end
a = Object.new
a.extend(FlyingCreature)
a.move_to(10) # -> flying to 10
a.extend(AfraidOfEvens)
a.move_to(10) # -> can’t fly to 10
// ???
struct Object
{
shared_ptr<ICanMoveTo> m_canMoveTo;
shared_ptr<IMoveTo> m_moveTo;
// ... every possible method ever
bool canMoveTo(int target) const {
return m_canMoveTo->call(target);
} // ... every possible method ever (again)
void extend(shared_ptr<Creature> c) {
c->setObject(this);
m_canMoveTo = c;
m_moveTo = c;
}
void extend(shared_ptr<ICanMoveTo> cmt) {
cmt->setObject(this);
m_canMoveTo = cmt;
} // ... every possible extension ever
};
// ... components
// ... virtual inheritence
// ... A LOT OF CODE
Object o;
o.extend(make_shared<FlyingCreature>());
o.moveTo(10); // flying to 10
o.extend(make_shared<AfraidOfEvens>());
o.moveTo(10); // can't fly to 10
DYNAMIX_MESSAGE_1(void, moveTo, int, target);
DYNAMIX_CONST_MESSAGE_1(bool, canMoveTo, int, target);
struct FlyingCreature {
void moveTo(int target) {
cout << (::canMoveTo(dm_this, target) ?
"flying to " : "can't fly to ")
<< target << '\n';
}
bool canMoveTo(int target) const {
return true;
}
}; DYNAMIX_DEFINE_MIXIN(FlyingCreature, moveTo_msg & canMoveTo_msg);
struct AfraidOfEvens {
bool canMoveTo(int target) const {
return target % 2 != 0;
}
}; DYNAMIX_DEFINE_MIXIN(AfraidOfEvens, priority(1, canMoveTo_msg));
int main() {
object o;
mutate(o).add<FlyingCreature>();
moveTo(o, 10); // flying to 10
mutate(o).add<AfraidOfEvens>();
moveTo(o, 10); // can't fly to 10
}
DYNAMIX_MESSAGE_1(void, moveTo, int, target);
DYNAMIX_CONST_MESSAGE_1(bool, canMoveTo, int, target);
struct FlyingCreature {
void moveTo(int target) {
cout << (::canMoveTo(dm_this, target) ?
"flying to " : "can't fly to ")
<< target << '\n';
}
bool canMoveTo(int target) const {
return true;
}
}; DYNAMIX_DEFINE_MIXIN(FlyingCreature, moveTo_msg & canMoveTo_msg);
struct AfraidOfEvens {
bool canMoveTo(int target) const {
return target % 2 != 0;
}
}; DYNAMIX_DEFINE_MIXIN(AfraidOfEvens, priority(1, canMoveTo_msg));
int main() {
object o;
mutate(o).add<FlyingCreature>();
moveTo(o, 10); // flying to 10
mutate(o).add<AfraidOfEvens>();
moveTo(o, 10); // can't fly to 10
}
DYNAMIX_MESSAGE_1(void, moveTo, int, target);
DYNAMIX_CONST_MESSAGE_1(bool, canMoveTo, int, target);
struct FlyingCreature {
void moveTo(int target) {
cout << (::canMoveTo(dm_this, target) ?
"flying to " : "can't fly to ")
<< target << '\n';
}
bool canMoveTo(int target) const {
return true;
}
}; DYNAMIX_DEFINE_MIXIN(FlyingCreature, moveTo_msg & canMoveTo_msg);
struct AfraidOfEvens {
bool canMoveTo(int target) const {
return target % 2 != 0;
}
}; DYNAMIX_DEFINE_MIXIN(AfraidOfEvens, priority(1, canMoveTo_msg));
int main() {
object o;
mutate(o).add<FlyingCreature>();
moveTo(o, 10); // flying to 10
mutate(o).add<AfraidOfEvens>();
moveTo(o, 10); // can't fly to 10
}
DYNAMIX_MESSAGE_1(void, moveTo, int, target);
DYNAMIX_CONST_MESSAGE_1(bool, canMoveTo, int, target);
struct FlyingCreature {
void moveTo(int target) {
cout << (::canMoveTo(dm_this, target) ?
"flying to " : "can't fly to ")
<< target << '\n';
}
bool canMoveTo(int target) const {
return true;
}
}; DYNAMIX_DEFINE_MIXIN(FlyingCreature, moveTo_msg & canMoveTo_msg);
struct AfraidOfEvens {
bool canMoveTo(int target) const {
return target % 2 != 0;
}
}; DYNAMIX_DEFINE_MIXIN(AfraidOfEvens, priority(1, canMoveTo_msg));
int main() {
object o;
mutate(o).add<FlyingCreature>();
moveTo(o, 10); // flying to 10
mutate(o).add<AfraidOfEvens>();
moveTo(o, 10); // can't fly to 10
}
DYNAMIX_MESSAGE_1(void, moveTo, int, target);
DYNAMIX_CONST_MESSAGE_1(bool, canMoveTo, int, target);
struct FlyingCreature {
void moveTo(int target) {
cout << (::canMoveTo(dm_this, target) ?
"flying to " : "can't fly to ")
<< target << '\n';
}
bool canMoveTo(int target) const {
return true;
}
}; DYNAMIX_DEFINE_MIXIN(FlyingCreature, moveTo_msg & canMoveTo_msg);
struct AfraidOfEvens {
bool canMoveTo(int target) const {
return target % 2 != 0;
}
}; DYNAMIX_DEFINE_MIXIN(AfraidOfEvens, priority(1, canMoveTo_msg));
int main() {
object o;
mutate(o).add<FlyingCreature>();
moveTo(o, 10); // flying to 10
mutate(o).add<AfraidOfEvens>();
moveTo(o, 10); // can't fly to 10
}
DYNAMIX_MESSAGE_1(void, moveTo, int, target);
DYNAMIX_CONST_MESSAGE_1(bool, canMoveTo, int, target);
struct FlyingCreature {
void moveTo(int target) {
cout << (::canMoveTo(dm_this, target) ?
"flying to " : "can't fly to ")
<< target << '\n';
}
bool canMoveTo(int target) const {
return true;
}
}; DYNAMIX_DEFINE_MIXIN(FlyingCreature, moveTo_msg & canMoveTo_msg);
struct AfraidOfEvens {
bool canMoveTo(int target) const {
return target % 2 != 0;
}
}; DYNAMIX_DEFINE_MIXIN(AfraidOfEvens, priority(1, canMoveTo_msg));
int main() {
object o;
mutate(o).add<FlyingCreature>();
moveTo(o, 10); // flying to 10
mutate(o).add<AfraidOfEvens>();
moveTo(o, 10); // can't fly to 10
}
MixQuest: github.com/iboB/mixquest
using foo_func_type = int (*)(float, MyType*);
foo_func_type foo_func;
void on_foo_file_changed() {
if (lib) dlclose(lib);
lib = dlopen("foo.so", RTLD_NOW);
foo_func = (foo_func_type)dlsym(lib, "foo_func");
}
MixQuest again: github.com/iboB/mixquest
C++: Runtime Compiled C++
Hotpatching: Edit-and-continue, Live++
serialize_state();
perform_hotswap();
deserialize_state();
Hotswapping C++ is real. Use it today!
Google chrome
Wait... We can have this in C++?
well... sortaRCRL: https://github.com/onqtam/rcrl
There is more.
The beast is back! - Jon Kalb
Borislav Stanimirov / ibob.github.io / @stanimirovb
Link to these slides: http://ibob.github.io/slides/bbb2cpp/
Slides license Creative Commons By 3.0