簡體   English   中英

為什么我的C ++模板化函數不會產生“未聲明的已識別”編譯錯誤?

[英]Why my C++ templated function does not produce `undeclared identified` compile error?

我正在嘗試創建一個關於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以最少的代碼重新創建問題。 我結束了在這里 顯然,我的問題的答案似乎是:

“代碼不應該編譯,但不知何故MSVC解決問題”

模板在編寫模板時,您可以假設模板參數。 即:

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

即使我們不知道T是否實際上有一個方法bar() ,編譯器此刻接受它,因為它只是一個“模板”,而不是實際的代碼。 在您使用一些參數實例化模板時,編譯器將檢查您所假設的正確性,因為現在它必須生成代碼。

在功能的情況下,它是相同的。 必須采用相同的邏輯,除非有人在標准中找到關於它的明確陳述 ,我試圖找到並且沒有。

如果我們遵循這個邏輯,當你編寫LoadLight的模板時,你假設存在一個名為LoadLightSpecific<T>的函數。 換一種說法,

為什么T.bar()bar<T>()在類模板中被接受,而不是在函數模板中被接受?

模板化函數不會在其模板化定義的位置進行轉換,而是在實際調用它時(類似於模板類的實例化 ),並使用一些特定的模板參數。 如果在那個地方,所有需要的東西都可用( LoadLightSpecific聲明),那么它將正常工作。

但是,我認為盡可能在模板定義的位置聲明事物是一種好的做法。 這樣可以更輕松地跟蹤依賴項。

對於這個特定的代碼:

如果在定義點的范圍內有一個名為LoadLightSpecific的函數模板,則此模板定義本身有效。 (它不必具有該簽名;甚至template<int> void LoadLightSpecific();也可以。)

原因是編譯器必須知道LoadLightSpecific是一個模板,以便解析<作為模板參數列表的開頭,而不是less-than運算符。

由於LoadLightSpecific<LightType> (如果解析為template-id )依賴於模板參數,因此LoadLightSpecific名稱查找將推遲到實例化。 (請注意,這並不意味着實例化必然會成功:不在模板定義上下文中的聲明只能通過ADL在實例化上下文中找到,而不能通過正常的非限定查找找到。)


在更一般的情況下,標准指定哪些名稱被認為依賴於模板參數而哪些不依賴於模板參數。 在模板定義時查找並綁定非依賴名稱:

如果名稱不依賴於模板參數 (如14.6.2中所定義),則該名稱的聲明(或聲明集)應在名稱出現在模板定義中的范圍內; 該名稱綁定到此時發現的聲明(或聲明),並且此綁定不受在實例化時可見的聲明的影響。


MSVC因其在該領域的不合格而聞名。

暫無
暫無

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

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