-1

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?

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
ZioByte
  • 2,690
  • 1
  • 32
  • 68
  • To be clear - you want some vector `v` such that the compiler does not know what `v[0]->get()` returns? It might return a `bool` or it might return a `float`? – Drew Dormann Feb 14 '23 at 00:25
  • How would you call it (where do you know `T` from)? – lorro Feb 14 '23 at 01:07
  • *"How can I achieve desired result: put in the same vector of pointers to slightly different template classes?"* -- I think you need more sentences to describe your desired result. If I go by just this description, one answer is to remove the `set` and `get` functions. *How do you see `set` being called from a vector element when you don't know what is a valid argument?* – JaMiT Feb 14 '23 at 03:06
  • @JaMiT I will review OP ASAP. Thanks. – ZioByte Feb 14 '23 at 13:55
  • 2
    You should not edit your question in a way that invalidates existing answers. (Besides, after the most recent edit, your question looks like an overly complex version of an existing question: [Why do I have to access template base class members through the this pointer?](https://stackoverflow.com/questions/4643074/)) – JaMiT Feb 16 '23 at 00:59

1 Answers1

1

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