Skip to content

Instantly share code, notes, and snippets.

@shintakezou
Created January 12, 2019 21:46
Show Gist options
  • Save shintakezou/5f20c7fc9be4e61092c8e3d3088fe127 to your computer and use it in GitHub Desktop.
Save shintakezou/5f20c7fc9be4e61092c8e3d3088fe127 to your computer and use it in GitHub Desktop.
Dynamic overloading simple poc test (dynamic dispatching)
#include <iostream>
// likely you'd like to use this someway; instead, this code
// simply ignores and accepts memory leaks.
//#include <memory>
#include <string>
#include <stack>
#include <sstream>
class Number;
class String;
struct Base
{
virtual ~Base() {}
virtual const Base* op_sum(const String* s) const = 0;
virtual const Base* op_sum(const Number* n) const = 0;
virtual const Base* op_sum(const Base* b) const = 0;
virtual std::string str() const = 0;
};
class Number : public Base
{
public:
Number(int n);
const Base* op_sum(const Number* n) const final override;
const Base* op_sum(const String* s) const final override;
const Base* op_sum(const Base* b) const final override;
int value() const;
std::string str() const final override;
private:
int n_;
};
class String : public Base
{
public:
String(const std::string& s);
virtual const Base* op_sum(const Number* n) const final override;
virtual const Base* op_sum(const String* s) const final override;
const Base* op_sum(const Base* b) const final override;
std::string value() const;
std::string str() const final override;
private:
std::string s_;
};
// implementation
Number::Number(int n) : n_(n) {}
int Number::value() const
{
return n_;
}
const Base* Number::op_sum(const Number* n) const
{
return new Number(n->value() + n_);
}
const Base* Number::op_sum(const String* s) const
{
std::ostringstream ss;
ss << n_ << s->value();
return new String(ss.str());
}
std::string Number::str() const
{
std::ostringstream ss;
ss << n_;
return ss.str();
}
// dispatcher for Number
const Base* Number::op_sum(const Base* b) const
{
if (dynamic_cast<const Number*>(b)) return this->op_sum(dynamic_cast<const Number*>(b));
else if (dynamic_cast<const String*>(b)) return this->op_sum(dynamic_cast<const String*>(b));
else throw std::runtime_error("dispatching error");
}
String::String(const std::string& s) : s_(s) {}
std::string String::value() const
{
return s_;
}
const Base* String::op_sum(const Number* n) const
{
std::ostringstream ss;
ss << s_ << n->value();
return new String(ss.str());
}
const Base* String::op_sum(const String* s) const
{
return new String(s_ + s->value());
}
std::string String::str() const
{
// should escape " in s_
return "\"" + s_ + "\"";
}
// dispatcher for String
const Base* String::op_sum(const Base* b) const
{
if (dynamic_cast<const Number*>(b)) return this->op_sum(dynamic_cast<const Number*>(b));
else if (dynamic_cast<const String*>(b)) return this->op_sum(dynamic_cast<const String*>(b));
else throw std::runtime_error("dispatching error");
}
std::stack<const Base*> stack;
int main()
{
stack.push(new Number(10));
stack.push(new Number(11));
stack.push(new Number(5));
stack.push(new String("x"));
stack.push(new String("13"));
stack.push(new Number(12));
stack.push(new String("a"));
stack.push(new String("bc"));
stack.push(new Number(1));
stack.push(new Number(2));
stack.push(new Number(3));
// memory leaks? we don't care
const Base* o1;
const Base* o2;
const Base* r;
for (const auto ops : std::string{"++.+.+.+.+."}) {
switch (ops) {
case '+':
o2 = stack.top(); stack.pop();
o1 = stack.top(); stack.pop();
stack.push(o1->op_sum(o2));
break;
case '.':
r = stack.top(); stack.pop();
std::cout << r->str() << "\n";
break;
default:
std::cerr << "unknown operator\n";
break;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment