Как переопределить базовый класс дочерним шаблоном?

У меня есть следующий код.

#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() на самом деле не переопределяют базовый класс.

Как я могу добиться желаемого результата: поместить один и тот же вектор указателей на немного разные классы шаблонов?

Чтобы было ясно: вам нужен вектор v, чтобы компилятор не знал, что возвращает v[0]->get()? Он может вернуть bool или может вернуть float?

Drew Dormann 14.02.2023 01:25

Как бы вы это назвали (откуда вы знаете T)?

lorro 14.02.2023 02:07

«Как я могу добиться желаемого результата: поместить один и тот же вектор указателей на немного разные классы шаблонов?» -- Я думаю, вам нужно больше предложений, чтобы описать желаемый результат. Если я воспользуюсь только этим описанием, один из ответов — удалить функции set и get. Как вы видите, что set вызывается из векторного элемента, когда вы не знаете, что является допустимым аргументом?

JaMiT 14.02.2023 04:06

@JaMiT Я рассмотрю ОП как можно скорее. Спасибо.

ZioByte 14.02.2023 14:55

Вы не должны редактировать свой вопрос таким образом, чтобы сделать недействительными существующие ответы. (Кроме того, после последнего редактирования ваш вопрос выглядит как слишком сложная версия существующего вопроса: Почему мне нужно обращаться к членам базового класса шаблона через указатель this?)

JaMiT 16.02.2023 01:59
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Laravel - это мощный PHP-фреймворк, используемый для создания масштабируемых и надежных веб-приложений. Одним из преимуществ Laravel является его...
Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание API-ресурса Laravel может быть непростой задачей. Она требует глубокого понимания возможностей Laravel и лучших практик, чтобы обеспечить...
Как сделать компонент справочного центра с помощью TailwindCSS
Как сделать компонент справочного центра с помощью TailwindCSS
Справочный центр - это веб-сайт, где клиенты могут найти ответы на свои вопросы и решения своих проблем. Созданный для решения многих распространенных...
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
1
5
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете попробовать что-то вроде следующего.

#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),
};

Другие вопросы по теме