使用带有模板参数的成员函数指针
Using a member function pointer with a template argument
我目前正在尝试制作一个通用函数,用于在另一个对象的 class(特别是 Shader
class)中设置各种值。以下是我尝试设置的一些示例:
void setBool(const std::string& name, bool value) const {
glUniform1i(glGetUniformLocation(shaderProgram, name.c_str()), (int)value);
}
void setInt(const std::string& name, int value) const {
glUniform1i(glGetUniformLocation(shaderProgram, name.c_str()), value);
}
void setFloat(const std::string& name, float value) const {
glUniform1f(glGetUniformLocation(shaderProgram, name.c_str()), value);
}
void setVec2(const std::string& name, const glm::vec2& value) const {
glUniform2fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, &value[0]);
}
void setVec3(const std::string& name, const glm::vec3& value) const {
glUniform3fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, &value[0]);
}
void setVec4(const std::string& name, const glm::vec4& value) const {
glUniform4fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, &value[0]);
}
void setMat2(const std::string& name, const glm::mat2& mat) const {
glUniformMatrix2fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void setMat3(const std::string& name, const glm::mat3& mat) const {
glUniformMatrix3fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void setMat4(const std::string& name, const glm::mat4& mat) const {
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
这是我尝试使用的函数:
template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&), const std::string& name, T value) {
for (auto iter = shaderMap.cbegin(); iter != shaderMap.cend(); ++iter) {
(iter->second->*fp)(name, T(value));
}
};
这是我的函数调用:
manager.setUniforms<const glm::mat4&>(&Shader::setMat4, "view", Camera::getLookMat());
其中Camera::getLookMat()
returns一个glm::mat4
。但是,当我尝试编译时,出现此错误:
Error C2664 'void ShaderManager::setUniforms<const glm::mat4&>(void (__thiscall Shader::* )(const std::string &,T),const std::string &,T)': cannot convert argument 1 from 'void (__thiscall Shader::* )(const std::string &,const glm::mat4 &) const' to 'void (__thiscall Shader::* )(const std::string &,T)' C2MEngine D:\Programming\C++\C2MEngine\src\testing\Main.cpp 85
有什么方法可以重新配置函数以使用列出的函数吗?此 post 中的所有函数都是成员函数,第二个代码块是与第一个块不同的 class 的一部分。我不确定是成员函数指针还是模板有问题。
您的成员函数指针中缺少 const
限定符:
template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&) const, const std::string& name, T value)
// added const here ~~~~^
虽然您所有的二传手都(令人惊讶!)const
合格。
重新格式化该错误消息:
Error C2664
'void ShaderManager::setUniforms<const glm::mat4&>(
void (__thiscall Shader::* )(const std::string &,T),
const std::string &,T)':
cannot convert argument 1 from
'void (__thiscall Shader::* )(const std::string &,const glm::mat4 &) const'
to
'void (__thiscall Shader::* )(const std::string &,T)'
C2MEngine D:\Programming\C++\C2MEngine\src\testing\Main.cpp 85
类型的一个区别当然是通用模板参数 T
代替特定类型 const glm::mat4&
。您将模板参数指定为 const glm::mat4&
,这样应该没问题。另一个区别是导致问题的原因:注意第一个函数指针类型末尾的 const
。
成员函数类型的 const
是函数类型的一部分,并且没有针对这些类型的指针的标准转换,以确保不会意外绕过常量正确性。
所以将最后的const
添加到函数指针类型中:
template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&) const,
const std::string& name,
T value);
(根据您问题中的声明进行了修改,尽管错误消息暗示函数指针的值参数的类型为 T
,而不是 const T&
。)
如果需要,您还可以使用别名模板来减少冗长,并使 fp
函数参数的名称更加明显:
template <class T> using ShaderSetFuncPtr =
void (Shader::*)(const std::string&, const T&); // or ,T ?
template <class T>
void setUniforms(ShaderSetFuncPtr<T> fp, const std::string& name, T value);
我目前正在尝试制作一个通用函数,用于在另一个对象的 class(特别是 Shader
class)中设置各种值。以下是我尝试设置的一些示例:
void setBool(const std::string& name, bool value) const {
glUniform1i(glGetUniformLocation(shaderProgram, name.c_str()), (int)value);
}
void setInt(const std::string& name, int value) const {
glUniform1i(glGetUniformLocation(shaderProgram, name.c_str()), value);
}
void setFloat(const std::string& name, float value) const {
glUniform1f(glGetUniformLocation(shaderProgram, name.c_str()), value);
}
void setVec2(const std::string& name, const glm::vec2& value) const {
glUniform2fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, &value[0]);
}
void setVec3(const std::string& name, const glm::vec3& value) const {
glUniform3fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, &value[0]);
}
void setVec4(const std::string& name, const glm::vec4& value) const {
glUniform4fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, &value[0]);
}
void setMat2(const std::string& name, const glm::mat2& mat) const {
glUniformMatrix2fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void setMat3(const std::string& name, const glm::mat3& mat) const {
glUniformMatrix3fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void setMat4(const std::string& name, const glm::mat4& mat) const {
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
这是我尝试使用的函数:
template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&), const std::string& name, T value) {
for (auto iter = shaderMap.cbegin(); iter != shaderMap.cend(); ++iter) {
(iter->second->*fp)(name, T(value));
}
};
这是我的函数调用:
manager.setUniforms<const glm::mat4&>(&Shader::setMat4, "view", Camera::getLookMat());
其中Camera::getLookMat()
returns一个glm::mat4
。但是,当我尝试编译时,出现此错误:
Error C2664 'void ShaderManager::setUniforms<const glm::mat4&>(void (__thiscall Shader::* )(const std::string &,T),const std::string &,T)': cannot convert argument 1 from 'void (__thiscall Shader::* )(const std::string &,const glm::mat4 &) const' to 'void (__thiscall Shader::* )(const std::string &,T)' C2MEngine D:\Programming\C++\C2MEngine\src\testing\Main.cpp 85
有什么方法可以重新配置函数以使用列出的函数吗?此 post 中的所有函数都是成员函数,第二个代码块是与第一个块不同的 class 的一部分。我不确定是成员函数指针还是模板有问题。
您的成员函数指针中缺少 const
限定符:
template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&) const, const std::string& name, T value)
// added const here ~~~~^
虽然您所有的二传手都(令人惊讶!)const
合格。
重新格式化该错误消息:
Error C2664
'void ShaderManager::setUniforms<const glm::mat4&>(
void (__thiscall Shader::* )(const std::string &,T),
const std::string &,T)':
cannot convert argument 1 from
'void (__thiscall Shader::* )(const std::string &,const glm::mat4 &) const'
to
'void (__thiscall Shader::* )(const std::string &,T)'
C2MEngine D:\Programming\C++\C2MEngine\src\testing\Main.cpp 85
类型的一个区别当然是通用模板参数 T
代替特定类型 const glm::mat4&
。您将模板参数指定为 const glm::mat4&
,这样应该没问题。另一个区别是导致问题的原因:注意第一个函数指针类型末尾的 const
。
成员函数类型的 const
是函数类型的一部分,并且没有针对这些类型的指针的标准转换,以确保不会意外绕过常量正确性。
所以将最后的const
添加到函数指针类型中:
template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&) const,
const std::string& name,
T value);
(根据您问题中的声明进行了修改,尽管错误消息暗示函数指针的值参数的类型为 T
,而不是 const T&
。)
如果需要,您还可以使用别名模板来减少冗长,并使 fp
函数参数的名称更加明显:
template <class T> using ShaderSetFuncPtr =
void (Shader::*)(const std::string&, const T&); // or ,T ?
template <class T>
void setUniforms(ShaderSetFuncPtr<T> fp, const std::string& name, T value);