簡體   English   中英

使用帶有模板參數的成員函數指針

[英]Using a member function pointer with a template argument

我目前正在嘗試創建一個通用函數,用於在另一個對象的類(特別是Shader類)中設置各種值。 以下是我嘗試設置的一些示例:

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()返回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  

有什么方法可以重新配置函數以使用列出的函數? 這篇文章中的所有函數都是成員函數,第二個代碼塊是與第一個代碼塊不同的類的一部分。 我不確定成員函數指針或模板是否有問題。

您的成員函數指針中缺少const限定符:

template <class T>
void setUniforms(void(Shader::*fp)(const std::string&, const T&) const, const std::string& name, T value)
//                                              added const here ~~~~^

雖然你所有的 setter 都是(令人驚訝的!) 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 正確性。

所以將最后的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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM