I have a project that I am working on where I have a command system that allows me to edit data on objects that inherit from a base class Component. I do this by storing a static vector of pointers to components and calling an overloaded assign function. I also have a similar system with Shaders that allows me to do the same with shader uniforms. (Shaders do not and cannot inherit from Component)
Right now both functions that are called have the same signature, i.e. int assign(string name, T value)
although they are not actually template functions, they are directly defined.
The way that I parse the command data right now is quite long, and I have it essentially copied between two code paths because I cannot seem to find a way to replace it with a more flexible solution that allows me to either pass component->assign or shader->assign to a function to parse the string and call them there or use template metaprogramming to achieve a similar effect.
I would like to do this because there are several other similar commands I would like to implement with a similar method, but I don't want to clutter my code with several copies of the same code.
Below is a working example with a shortened parsing and assigning section.
#include <iostream>#include <functional>#include <string>#include <sstream>#include <vector>#include <map>using namespace std;class Shader { public: int assign(string n, int value) {return 1;}; int assign(string n, string value) {return 1;}; static map<string, Shader *> shaders; Shader(string n) { shaders[n] = this; };};class Component { public: int assign(string n, int value) {return 1;}; int assign(string n, string value) {return 1;}; static map<string, Component *> components; Component(string n) { components[n] = this; };};class Transform : public Component { public: int assign(string n, int value) {return 1;}; int assign(string n, string value) {return 1;}; Transform(string n) : Component(n) { }};//// Several more similar classes//map<string, Shader *> Shader::shaders;map<string, Component *> Component::components;int main() { Component first("first"); Transform second("second"); Shader third("third"); cout << "Enter command: " << endl; string command; cin >> command; istringstream iss(command); string type; iss >> type; string name; iss >> name; string valueName; iss >> name; string value; iss >> value; if (type == "SHADER") { Shader *shader = Shader::shaders[name]; // This section if (isdigit(value[0])) { shader->assign(valueName, stoi(value)); } else { shader->assign(valueName, value); } } else if (type == "COMPONENT") { Component *component = Component::components[name]; // This one too if (isdigit(value[0])) { component->assign(valueName, stoi(value)); } else { component->assign(valueName, value); } } return 0;}// Actual parsing section:// if (value == "true" || value == "false") {// success = component->assign(assignName, value == "true");// }// else if (isdigit(value.at(0)) || value[0] == '-') {// if (value.find('') == value.npos) {// float f = stof(value);// int i = stoi(value);// if (f != i) {// success = component->assign(assignName, f);// }// else {// success = component->assign(assignName, i);// }// }// else {// int n;// float num;// vector<float> nums;// istringstream vec(value);// while (vec >> num) {// nums.push_back(num);// n++;// }// if (n == 2) {// success = component->assign(assignName, glm::vec2(nums[0], nums[1]));// }// if (n == 3) {// success = component->assign(assignName, glm::vec3(nums[0], nums[1], nums[2]));// }// if (n == 4) {// success = component->assign(assignName, glm::vec4(nums[0], nums[1], nums[2], nums[3]));// }// }// }// else {// success = component->assign(assignName, value);// }
I've tried a solution where I create a function: int assignTo(function<int(string, T)>, string value), but this clearly doesn't work because T needs to vary inside the function, and I also can't pass the member function anyways. I'm not sure where to go from here.