我有一个结构,定义如下:
template<typename T>
struct Variable
{
char *name;
constexpr Variable(char *setName) : name(setName)
{
}
};
我想创建一个类,其模板参数是这些结构的列表。到目前为止,我能得到的最接近的是:
template<template<typename TF> Variable First, template<TA...> typename Variable ... Args>
class UniformBuffer
{
};
UniformBuffer可能会声明如下:
// vec3 and vec4 are types defined elsewhere
UniformBuffer light<Variable<vec3>("location"), Variable<vec4>("rotation"), Variable<float>("intensity")>;
不幸的是,这不会编译,在“变量”之前给出错误“预期'类'”(尽管在其中放置“class”只会产生另一个错误,说它在'变量'之后预期'&gt;' )。即使查看关于可变参数模板的各种其他有趣的问题,我似乎也无法找到答案。我正在尝试做什么的正确语法是什么?
答案 0 :(得分:3)
看来你正在寻找专业化:
template<typename First, typename... Args>
class UniformBuffer;
template<typename First, typename... Args>
class UniformBuffer<Variable<First>,Variable<Args>...>
{
};
答案 1 :(得分:1)
您不能将Variable
的对象作为模板参数传递,因为它无法在编译时推断出来。
Here是一个解释
的答案答案 2 :(得分:1)
不允许在模板参数中传递类实例,因为模板参数需要编译时解析的东西(如常量,函数名,类型)。
不幸的模板参数不能是字符串文字。
您可以做的是将这些实例传递给辅助函数,从中可以根据这些实例的类型生成类似tuple
的对象。
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);
...
}
MakeUniformBuffer
将实例传递给UniformBuffer
的构造函数。 UniformBuffer
必须解压缩变量模板参数。
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...) {}
...
};
可以在UniformBuffer
上实现set和get方法,以按名称检索缓冲区元素。下面是如何实现get方法的说明:
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);
...
}