You are not allowed to pass class instances in as template arguments, since template arguments require compile time resolved things (like constants, function names, types).
It is unfortunate template arguments cannot be string literals.
What you can do is pass those instances into a helper function, from which you can generate a tuple
-like object based on the types of those instances.
template <typename T>
struct Variable
{
typedef T Type;
const char *name;
T val;
constexpr Variable (const char *setName) : name(setName) {}
operator T () const { return val; }
operator T & () { return val; }
};
template <typename... V> UniformBuffer<V...> MakeUniformBuffer (V... args) {
return UniformBuffer<V...>(args...);
}
{
Variable<vec3> loc("location");
Variable<vec4> rot("rotation");
Variable<float> amp("intensity");
auto ub = MakeUniformBuffer(loc, rot, amp);
...
}
The MakeUniformBuffer
passes the instances into the constructor of UniformBuffer
. UniformBuffer
has to unpack the variable template arguments.
template <typename... V> class UniformBuffer;
template <typename V>
struct UniformBuffer <V> {
V val;
UniformBuffer(V v) : val(v) {}
...
};
template <typename V, typename... VV>
struct UniformBuffer<V, VV...> {
V val;
UniformBuffer<VV...> ub;
UniformBuffer(V v, VV... rest) : val(v), ub(rest...) {}
...
};
It is possible to implement set and get methods on UniformBuffer
to retrieve buffer elements by name. Below is an illustration of how to implement a get method:
template <typename V>
struct UniformBuffer <V> {
...
typename V::Type get (const Variable<typename V::Type> &v) {
if (v.name != val.name) throw v.name;
return val;
}
template <typename R> R get (const Variable<R> &v) {
throw v.name;
return R();
}
};
template <typename V, typename... VV>
struct UniformBuffer<V, VV...> {
...
typename V::Type get (const Variable<typename V::Type> &v) {
if (v.name != val.name) return ub.get(v);
return val;
}
template <typename R> R get (const Variable<R> &v) {
return ub.get(v);
}
};
{
...
auto ub = MakeUniformBuffer(loc, rot, amp);
auto r = ub.get(rot);
...
}