为什么我的C ++模板化函数不会产生“未声明的已识别”编译错误?

时间:2015-11-23 02:53:50

标签: c++ templates

我正在尝试创建一个关于Lights的抽象(我用C ++构建游戏),并且我使用模板来做到这一点。我现在的部分代码是:

// Light.hpp
template <typename LightType>
void LoadLight(GLuint shaderId, const LightType& light, const std::string& glslUniformName)
{
    // Load common light attributes
    glUniform3f(glGetUniformLocation(lightingShader.GetProgID(), (glslUniformName + ".ambient").c_str()),  light.ambient.x,  light.ambient.y,  light.ambient.z);
    glUniform3f(glGetUniformLocation(lightingShader.GetProgID(), (glslUniformName + ".diffuse").c_str()),  light.diffuse.x,  light.diffuse.y,  light.diffuse.z);
    glUniform3f(glGetUniformLocation(lightingShader.GetProgID(), (glslUniformName + ".specular").c_str()), light.specular.x, light.specular.y, light.specular.z);

    // Load specific light attributes
    LoadLightSpecific<LightType>(shaderId, light, glslUniformName); // ???
}

template <typename LightType>
void LoadLightSpecific(GLuint shaderId, const LightType& light, const std::string& glslUniformName);

LoadLightSpecific的专精位于单独的.cpp文件中,与我的问题无关。

我的问题与???一致。 我在定义之前使用LoadLightSpecific!我认为这会给我一个undeclared identifier(或类似的东西)编译错误但没有。它正常工作。

为什么会这样?我觉得我错过了一些明显的东西。

更新2015年11月23日

因此,正如人们在评论中建议的那样,我使用Wandbox以最少的代码重新创建问题。我结束了here。显然,我的问题的答案似乎是:

&#34;代码应该不能编译,但不知何故MSVC解决了问题&#34;

1 个答案:

答案 0 :(得分:4)

模板在编写模板时,假设有关模板参数的内容并不罕见。即:

Template<class T>
class C
{ 
    void foo() { T.bar(); }
};

即使我们不知道T是否实际上有一个方法bar(),编译器此刻也会接受它,因为它只是一个“模板”,而不是实际的代码。当您使用一些参数实例化模板时,编译器将检查您所假设的正确性,因为现在它必须生成代码。

在功能的情况下,它是相同的。 必须采用相同的逻辑,除非有人在标准中找到关于它的明确陈述,我试图找到并且没有。

如果我们遵循这个逻辑,当您编写LoadLight模板时,假设存在一个名为LoadLightSpecific<T>的函数。换句话说,

为什么T.bar()bar<T>()会在类模板中被接受,而不会在函数模板中被接受?

模板化函数不是在其模板化定义的位置进行转换,而是在实际调用它时(类似于模板化类的实例化),并带有一些特定的模板参数。如果在那个地方,所有需要的东西都可用(LoadLightSpecific声明),那么它将正常工作。

但是,我认为尽可能在模板定义的位置声明事物是一种好习惯。这样可以更轻松地跟踪依赖关系。