Skip to content

Instantly share code, notes, and snippets.

@srele96
Created November 30, 2023 22:27
Show Gist options
  • Save srele96/603b62285d921ea40399118e8b2548a5 to your computer and use it in GitHub Desktop.
Save srele96/603b62285d921ea40399118e8b2548a5 to your computer and use it in GitHub Desktop.
You are given a sequence of operations to perform on a list of mixed data types. The data types can include integers, strings, and floating-point numbers. Each operation will specify the type of data it should be applied to and a specific action to perform. Your task is to process these operations efficiently using type erasure in C++.
#include <iostream>
#include <memory>
#include <vector>
class object_ {
private:
struct concept_ {
virtual void process(const std::string& p_value) = 0;
virtual void out(std::ostream& p_ostream) const = 0;
virtual ~concept_() = default;
};
template <typename T>
struct model_ : concept_ {
model_(const T& p_object) : m_object{p_object} {}
void process(const std::string& p_value) override {
m_object.process(p_value);
}
void out(std::ostream& p_ostream) const override {
m_object.out(p_ostream);
}
T m_object;
};
std::shared_ptr<concept_> m_object;
public:
template <typename T>
object_(T&& p_object)
: m_object{std::make_shared<model_<T>>(std::forward<T>(p_object))} {}
// So any object_ is only processable, and that's it? Did I get it right?
void process(const std::string& p_value) { m_object->process(p_value); }
void out(std::ostream& p_ostream) const { m_object->out(p_ostream); }
};
class integer_ {
private:
int m_value;
public:
integer_(const std::string& p_value) : m_value{std::stoi(p_value)} {}
void process(const std::string& p_value) { m_value += std::stoi(p_value); }
void out(std::ostream& p_ostream) const { p_ostream << m_value << "\n"; }
};
class string_ {
private:
std::string m_value;
public:
string_(const std::string& p_value) : m_value{p_value} {}
void process(const std::string& p_value) { m_value += p_value; }
void out(std::ostream& p_ostream) const { p_ostream << m_value << "\n"; }
};
class float_ {
private:
float m_value;
public:
float_(const std::string& p_value) : m_value{std::stof(p_value)} {}
void process(const std::string& p_value) { m_value *= std::stof(p_value); }
void out(std::ostream& p_ostream) const { p_ostream << m_value << "\n"; }
};
int main() {
int t;
std::cin >> t;
std::vector<std::pair<std::string, object_>> pairs;
while (t-- > 0) {
// Doesn't matter as long as it produces the expected output.
std::string operation, type, value;
std::cin >> operation >> type >> value;
if (operation == "Add") {
if (type == "int") {
pairs.push_back({"int", integer_{value}});
} else if (type == "string") {
pairs.push_back({"string", string_{value}});
} else if (type == "float") {
pairs.push_back({"float", float_{value}});
}
} else if (operation == "Process") {
for (auto& pair : pairs) {
if (pair.first == type) {
pair.second.process(value);
}
// Questions from the state of confusion:
//
// How should the generic container process the data?
// How should the public API look like?
}
}
}
for (const auto& pair : pairs) {
pair.second.out(std::cout);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment