![](/img/trans.png)
[英]Puzzling difference of variadic template method behavior for templated and non templated classes
[英]Variadic Template of Templated Classes
我有一个结构,定义如下:
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'在'Variable'之前”(尽管将“ class”放进去只是产生了另一个错误,说它在'Variable之后期望了'>')。 即使查看有关可变参数模板的其他各种有趣的问题,我似乎也无法找到答案。 我要做什么的正确语法是什么?
看来您正在寻找专业化领域:
template<typename First, typename... Args>
class UniformBuffer;
template<typename First, typename... Args>
class UniformBuffer<Variable<First>,Variable<Args>...>
{
};
您不能将Variable
对象作为模板参数传递,因为无法在编译时推导它。
这是一个解释,说明
不允许将类实例作为模板参数传递,因为模板参数需要编译时解析的东西(例如常量,函数名称,类型)。
不幸的是模板参数不能是字符串文字。
您可以做的是将这些实例传递到一个辅助函数中,从中可以根据这些实例的类型生成类似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);
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.