对于我的一个项目,我需要使用可变参数模板.一切都运作良好,除了参数的解包.
这是电话
Shader<GL_VERTEX_SHADER> vert(vertexShaderSource);
Shader<GL_FRAGMENT_SHADER> frag(fragmentShaderSource);
Program prog(vert, frag);
Run Code Online (Sandbox Code Playgroud)
以及导致问题的类
class Program
{
public:
template <class... Args>
Program(Args... args) :
program_(glCreateProgram())
{
auto shaders {{args...}};
std::for_each(shaders.begin(), shaders.end(), [this](auto s)
{
std::cout << "glAttachShader\n";
glAttachShader(program_, s.get_shader());
});
}
};
Run Code Online (Sandbox Code Playgroud)
而错误
fatal error: cannot deduce type for variable 'shaders' with type 'auto' from nested initializer list
auto shaders {{args...}};
Run Code Online (Sandbox Code Playgroud)
我尝试了几件事,比如
auto shaders = {args...};
auto shaders = {{args...}};
auto shaders {args...};
Run Code Online (Sandbox Code Playgroud)
但没有任何作用.
这是Shader类,以防万一
template <GLenum type>
class Shader
{
public:
Shader(std::string const &source)
{
char const *src = source.c_str();
shader_ = glCreateShader(type);
glShaderSource(shader_, 1, &src, NULL);
glCompileShader(shader_);
}
~Shader()
{
glDeleteShader(shader_);
}
inline GLuint get_shader()
{
return shader_;
}
private:
GLuint shader_;
};
Run Code Online (Sandbox Code Playgroud)
谢谢!
这不是关于可变参数模板解包的.问题是在声明着色器时,您需要告诉它的类型.它是矢量,数组,元组等吗?由于您正在使用可变参数模板,因此我猜测着色器可以有不同的类型.然后你必须使用元组.
auto shaders = std::make_tuple(args...);
Run Code Online (Sandbox Code Playgroud)
迭代一个元组并不像stl容器那样微不足道.这是一个使用递归的例子.
template <size_t i = 0,
class Fun,
class Tuple,
size_t N = std::tuple_size<typename std::decay<Tuple>::type>::value,
std::enable_if_t<i >= N>* = nullptr> // if i >= N
void tuple_for_each(Tuple&& t, Fun f) {} // end case
template <size_t i = 0,
class Fun,
class Tuple,
size_t N = std::tuple_size<typename std::decay<Tuple>::type>::value,
std::enable_if_t<i < N>* = nullptr> // if i < N
void tuple_for_each(Tuple&& t, Fun f) {
f(std::get<i>(std::forward<Tuple>(t))); // current iteration
tuple_for_each<i+1>(std::forward<Tuple>(t), std::move(f)); // call next
}
Run Code Online (Sandbox Code Playgroud)
总的来说,它非常直观,我们从i = 0开始,调用f()然后使用递归来遍历每个i直到N. C++ 14允许你避免使用std :: integer_sequence进行递归,你可以搜索它.
如果您对此&&胡说八道感到疑惑,我建议您阅读有关Universal References的内容.简而言之,它允许您使用引用来防止复制参数,同时可以处理r值.我建议你在程序构造函数中为Args做同样的事情.
然后我们可以使用tuple_for_each来做
tuple_for_each(shaders, [this](auto s) {
std::cout << "glAttachShader\n";
glAttachShader(program_, s.get_shader());
});
Run Code Online (Sandbox Code Playgroud)