"No matching function" 调用函数模板时出错

"No matching function" error with call to function template

我想使用 GLM 矩阵 header-only 库为我的 C++ 图形项目创建转换矩阵。为了对此进行测试,我编写了以下简单代码:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

int main()
{
    glm::mat4 projection_matrix = glm::perspective(45, 1.5, 0.1, 100);
    return 0;
}

但是,我收到以下编译错误:

/home/Karnivaurus/Projects/GLMTest/src/main.cpp:6: error: no matching function for call to 'perspective(int, double, double, int)'
     glm::mat4 projection_matrix = glm::perspective(45, 1.5, 0.1, 100);
                                                                     ^
                                                                     ^

其次是:

candidate is:
/usr/local/include/glm/gtc/matrix_transform.inl:218: template<class T> glm::detail::tmat4x4<T, (glm::precision)0u> glm::perspective(const T&, const T&, const T&, const T&)
  GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> perspective
                                                  ^

在提供的源代码中查看此功能的实现,我可以看到:

template <typename T>
    GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> perspective
    (
        T const & fovy,
        T const & aspect,
        T const & zNear,
        T const & zFar
    )
    {
    //
    // The implementation ..........
    // .....
    // .....
    //
    }

我不是特别熟悉 C++ 中的模板。有人可以向我解释这个错误吗?

函数模板的所有参数都使用一个模板参数定义。您正在为参数传递不同的类型,第一个和最后一个参数为 int,中间参数为 double

解决方法是始终对所有参数使用 doubles:

glm::mat4 projection_matrix = glm::perspective(45.0, 1.5, 0.1, 100.0);

您可以将示例简化为:

template <typename T>
void foo(const T&, const T& )
{ }

int main(){
    foo(45, 1.0); // error: no matching function for call to foo(int, double)
}

那是因为模板推导发生时,第一个参数推导Tint,第二个参数推导double,但只有一个T所以它必须是一致的!模板推导不会发生转换(这里 intdouble 可以相互转换并不重要),所以一旦我们得到不一致的类型,推导就会失败 - 因为只有一个 foo,没有其他重载可以依靠。

解决方案要么是确保类型相同:

foo(45.0, 1.0); // calls foo<double>
foo(45, 1);     // calls foo<int>

或明确指定 T 是什么:

foo<double>(45, 1.0);  // calls foo<double>, explicitly

在后一种情况下,因为我们指定了T,所以没有扣除发生,这相当于调用了:

void foo(const double&, const double& );

所以第一个参数只是转换为 double.

声明函数时,必须将其所有参数推导为同一类型T。在您的调用中,您提供了两个 int 和两个 double。它们不相同,因此实例化失败。

将您的呼叫更改为:

glm::mat4 projection_matrix = glm::perspective(45.0, 1.5, 0.1, 100.0);

您还可以明确指定类型以启用转换:

glm::mat4 projection_matrix = glm::perspective<double>(45, 1.5, 0.1, 100);