I have the following code.
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <cmath>
class Configuration {
protected:
static std::map<std::string, Configuration*> commands;
static std::vector<Configuration*> commidx;
const std::string name;
const int index;
int (*snippet)(float);
public:
Configuration(std::string name, const int index, int (*snippet)(float))
: name(std::move(name)), index(index), snippet(snippet) {}
virtual ~Configuration() = default;
virtual void set(float val) {} //should we raise an error?
virtual float get() { return NAN; } //should we raise an error?
};
template<typename T>
class Config : public Configuration {
const std::string type;
const std::string def;
T cur, min, max;
public:
explicit Config(const char *name, int index, const char *_type, const char *def, int (*snippet)(float), T min , T max)
: Configuration(name, index, snippet)
, type(_type)
, def(def)
, min(min)
, max(max)
{
if (type == "float") {
cur = std::stof(def);
} else if (type == "integer") {
cur = std::stoi(def);
} else if (type == "bool") {
cur = std::stof(def) != 0;
} else {
SPDLOG_ERROR("unknownt type {}", type);
}
}
void set(T val) override {
if (val < min) val = min;
if (val > max) val = max;
if (val != cur) {
val = cur;
snippet(val);
}
}
T get() override {
return cur;
}
};
std::vector<Configuration*> Configuration::commidx {
new Config<float>("fff", 0, "float", "0.4", nullptr, 0, 1),
new Config<bool>("bbb", 1, "bool", "0", nullptr, 0, 1),
new Config<integer>("iii", 8, "int", "0", nullptr, 0, 3),
};
This bombs in compilation because set() and get() methods don't really override base class.
How can I achieve desired result: put in the same vector of pointers to slightly different template classes?
You can try something like following.
#include <string>
#include <map>
#include <utility>
#include <vector>
#include <cmath>
class Configuration
{
protected:
static std::map<std::string, Configuration *> commands;
static std::vector<Configuration *> commidx;
const std::string name;
const int index;
int (*snippet)(float);
public:
Configuration(std::string name, const int index, int (*snippet)(float))
: name(std::move(name)), index(index), snippet(snippet) {}
virtual ~Configuration() = default;
};
template <typename T>
class ConfigurationBase : public Configuration
{
public:
ConfigurationBase(std::string name, const int index, int (*snippet)(float))
: Configuration(name, index, snippet)
{
}
//virtual void set(T val) {}
//virtual T get() { return NAN; }
virtual void set(T val) = 0;
virtual T get() = 0;
};
template <typename T>
class Config : public ConfigurationBase<T>
{
const std::string type;
const std::string def;
T cur, min, max;
public:
explicit Config(const char *name, int index, const char *_type, const char *def, int (*snippet)(float), T min, T max)
: ConfigurationBase<T>(name, index, snippet), type(_type), def(def), min(min), max(max)
{
if (type == "float")
{
cur = std::stof(def);
}
else if (type == "integer")
{
cur = std::stoi(def);
}
else if (type == "bool")
{
cur = std::stof(def) != 0;
}
else
{
// SPDLOG_ERROR("unknownt type {}", type);
}
}
void set(T val) override
{
if (val < min)
val = min;
if (val > max)
val = max;
if (val != cur)
{
val = cur;
// snippet(val);
}
}
T get() override
{
return cur;
}
};
std::vector<Configuration *> Configuration::commidx{
new Config<float>("fff", 0, "float", "0.4", nullptr, 0, 1),
new Config<bool>("bbb", 1, "bool", "0", nullptr, 0, 1),
new Config<int>("iii", 8, "int", "0", nullptr, 0, 3),
};