2

This question was marked duplicate to a solution that uses boost for keeping dynamic polymorphism, even though i stated explicitly that I can't use boost.

I want to have multiple contexts that are instanciated somewhere else. Now we want to set key-value variables to some value of type T, context-dependent.

A variable class is a handle to set an arbitrary type to some value.

Each context handles the variable setting differently (namely these are graphics backends.) For that, the Context::magically_set method could be specialized for each supported T.

But each context handles each supported T differently.

Here's my "working" code if virtual member functions could be templated:

class Context {
public:
    template<typename T>
    virtual void magically_set(const T &value);
};

class ContextA : public Context {
public:
    template<typename T>
    void magically_set(const std::string &name, const T &value) override;
    // somewhere else: T-specific implementation for this context.
};

class ContextB : public Context {
public:
    template<typename T>
    void magically_set(const std::string &name, const T &value) override;
    // somewhere else: T-specific implementation for this different context.
};

template<typename T>
class Variable {
public:
    Variable(std::string name, Context *context)
        : name{name}, context{context} {}

    void set(const T &value) {
        this->context->magically_set(this->name, value);
    }

    std::string name;
    Context *context;
};

and the usage:

ContextB ctx_b;
Variable<float> test{"index", &ctx_b};
Variable<vec3> vectest{"color", &ctx_b};
test.set(0.1337f);
vectest.set({0.0, 0.0, 1.0});

How can I make this work? I can use anything supported by c++14, but no boost.

TheJJ
  • 931
  • 12
  • 21
  • Does context has a limited number of `T` supported ? – Jarod42 Aug 28 '15 at 16:52
  • Yes, because each `T` needs special handling (we're talking about shader uniforms here.) – TheJJ Aug 28 '15 at 16:58
  • 2
    So you may have several `virtual void magically_set`, one by supported type. – Jarod42 Aug 28 '15 at 17:01
  • Why was the question flagged duplicate? I stated that I can't use boost, and the "duplicate" uses boost as the only option for maintaining dynamic polymorphism... @Jarod42, yes this is a good idea although it will severely clutter the base class. Thanks though! – TheJJ Aug 28 '15 at 23:22

1 Answers1

1

If you don't have problems to supply the Context to the Variable you could do something like the following:

template<typename T, typename C>
class Variable {
public:
    Variable(std::string name, C &context)
        : name{name}, context{context} {}

    void set(const T &value) {
        this->context->magically_set(this->name, value);
    }

    std::string name;
    C &context;
};

you now have to declare the Variables as follows:

typedef ContextB ActiveContext;

ContextB ctx_b;
Variable<float, ActiveContext> test{"index", ctx_b};
Variable<vec3, ActiveContext> vectest{"color", ctx_b};
test.set(0.1337f);
vectest.set({0.0, 0.0, 1.0});

PS: you should make Variable::name and Variable::context private.

Jujuedv
  • 11
  • 2
  • Sorry, but this would lead to a compiletime context dependency, but the context selection must happen dynamically. – TheJJ Aug 28 '15 at 23:19