Can this code be considered good design?
It compiles and works fine, both with GCC and Visual Studio. The slot object ends up really small, neatly packed and easy to reason about.
However, how much the casting will slow down my program in the end?
If I ended up using boost::any
or boost::variant
I would still put them in a std::shared_ptr
because I do need it to be a smart pointer.
I'm using C++14.
//EDITED BEGIN
Context: I'm builing an interpreter, something in the vein of lisp / ruby. I want slot objects to be a sort of god object. I want to be able to construct and return new slot objects inside the slot object itself, both shallow and deep copies. The data in the slot object is a pointer because I intend that data to be shared between objects. The slot_t enumerator exists mainly to be used in switch statements and it needs to be accessible outside the slot class, that's why it was made global. The slot_t in the constructor is needed because sometimes a type can have the same internal representation, and thus a mean to disambiguation is needed. The example I gave was rushed and it does have some problems.
This is how I envision my slot object:
4 members -> gate (variable / constant, ...), type, data and docstring.
Operator overloads -> bool, ==, !=, <, > <=, >=.
Some methods: copy, deep_copy, get_type(by returning a new slot), etc...
I think you did get the point. :D
This is my rushed example:
//EDITED END
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
using std::cout;
using std::endl;
enum class slot_t {
number_t,
string_t
};
class slot {
public:
slot_t type;
std::shared_ptr<void> data;
slot(slot_t const p_type, double long const & p_data)
: type {p_type}
, data {std::make_shared<double long>(p_data)}
{}
slot(slot_t const p_type, std::string const & p_data)
: type {p_type}
, data {std::make_shared<std::string>(p_data)}
{}
std::string get_type() const {
std::ostringstream output;
switch (type) {
case slot_t::string_t: output << "String: " << as<std::string>(); break;
case slot_t::number_t: output << "Number: " << as<double long>(); break;
}
return output.str();
}
template <typename t>
t as() const {
return *std::static_pointer_cast<t>(data);
}
};
int main() {
slot hello {slot_t::number_t, 123};
slot world {slot_t::string_t, "Hello, world!"};
cout << hello.as<double long>() << endl;
cout << world.as<std::string>() << endl;
cout << hello.get_type() << endl;
cout << world.get_type() << endl;
return 0;
}