У меня есть следующий код.
#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),
};
Это бомба при компиляции, потому что методы set() и get() на самом деле не переопределяют базовый класс.
Как я могу добиться желаемого результата: поместить один и тот же вектор указателей на немного разные классы шаблонов?
Как бы вы это назвали (откуда вы знаете T)?
«Как я могу добиться желаемого результата: поместить один и тот же вектор указателей на немного разные классы шаблонов?» -- Я думаю, вам нужно больше предложений, чтобы описать желаемый результат. Если я воспользуюсь только этим описанием, один из ответов — удалить функции set и get. Как вы видите, что set вызывается из векторного элемента, когда вы не знаете, что является допустимым аргументом?
@JaMiT Я рассмотрю ОП как можно скорее. Спасибо.
Вы не должны редактировать свой вопрос таким образом, чтобы сделать недействительными существующие ответы. (Кроме того, после последнего редактирования ваш вопрос выглядит как слишком сложная версия существующего вопроса: Почему мне нужно обращаться к членам базового класса шаблона через указатель this?)
Вы можете попробовать что-то вроде следующего.
#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),
};
Чтобы было ясно: вам нужен вектор v, чтобы компилятор не знал, что возвращает v[0]->get()? Он может вернуть bool или может вернуть float?