我正在尝试创建一个关于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;
答案 0 :(得分:4)
模板在编写模板时,假设有关模板参数的内容并不罕见。即:
Template<class T>
class C
{
void foo() { T.bar(); }
};
即使我们不知道T
是否实际上有一个方法bar()
,编译器此刻也会接受它,因为它只是一个“模板”,而不是实际的代码。当您使用一些参数实例化模板时,编译器将检查您所假设的正确性,因为现在它必须生成代码。
在功能的情况下,它是相同的。 必须采用相同的逻辑,除非有人在标准中找到关于它的明确陈述,我试图找到并且没有。
如果我们遵循这个逻辑,当您编写LoadLight
模板时,假设存在一个名为LoadLightSpecific<T>
的函数。换句话说,
为什么T.bar()
和bar<T>()
会在类模板中被接受,而不会在函数模板中被接受?
模板化函数不是在其模板化定义的位置进行转换,而是在实际调用它时(类似于模板化类的实例化),并带有一些特定的模板参数。如果在那个地方,所有需要的东西都可用(LoadLightSpecific
声明),那么它将正常工作。
但是,我认为尽可能在模板定义的位置声明事物是一种好习惯。这样可以更轻松地跟踪依赖关系。