簡體   English   中英

函數模板的顯式特化會導致鏈接器錯誤

[英]Explicit specialization of function templates causes linker error

Functions.h:

#pragma once
#include <iostream>

template<class T> void TemplatedFunction(T* p) {}

template<> void TemplatedFunction<float>(float* p) {}

template<> void TemplatedFunction<char>(char* p) {}

Functions.cpp:

#include "Functions.h"

void Test()
{
    TemplatedFunction<float>(NULL);
    TemplatedFunction<char>(NULL);
}

main.cpp中:

#include "Functions.h"
void Test();

int main()
{
    Test();
    return 0;
}

構建錯誤:

main.obj : error LNK2005: "void __cdecl TemplatedFunction<float>(float *)" (??$TemplatedFunction@M@@YAXPAM@Z) already defined in Functions.obj
main.obj : error LNK2005: "void __cdecl TemplatedFunction<char>(char *)" (??$TemplatedFunction@D@@YAXPAD@Z) already defined in Functions.obj

我知道有兩種解決方法:

  1. 不要將Functions.h包含在幾個.cpp文件中 - 如果h文件包含許多.cpp文件中需要的一些附加定義,則不能在復雜項目中應用。

  2. 將所有模板化函數聲明為static 但這意味着專用函數出現在包含Functions.h的所有.cpp文件中,即使它們未被使用,也可能導致代碼重復。

所以,我看到專門的模板化函數表現得像非模板化函數。 是否還有其他解決方案可以在沒有static聲明的情 如果函數聲明為static ,那么現代C ++編譯器是否會從優化構建中刪除它們(如果它們未被使用)?

編輯。 在閱讀前兩個答案后:我不在這里問如何防止這樣的鏈接器錯誤。 假設我無法將專門化移動到.cpp文件並將其保留在帶有staticinline .h文件中,當這些函數被添加到包含.h文件的每個.cpp文件時,這是否會導致代碼重復和膨脹優化的構建,即使他們沒有被使用?

所以,我看到專門的模板化函數表現得像非模板化函數。

正確。

是否還有其他解決方案可以在沒有static聲明的情

是的,就像任何普通的非模板功能一樣:

將函數專定義為inline

聲明(但不定義)標題中的特化:

template<> void TemplatedFunction<float>(float* p);

template<> void TemplatedFunction<char>(char* p);

並在Functions.cpp定義它們

template<> void TemplatedFunction<float>(float* p) {}

template<> void TemplatedFunction<char>(char* p) {}

這些是比使用static更好的選項,因為使函數靜態具有其他副作用,例如在每個翻譯單元中賦予函數不同的地址,以及在每個翻譯單元中使本地靜態變量不同。 這是一個語義變化,而不僅僅是鏈接器錯誤的解決方案。

如果函數聲明為static ,那么現代C ++編譯器是否會從優化構建中刪除它們(如果它們未被使用)?

是。 但是在使用它們的任何文件中,您將獲得重復的代碼,使得可執行文件比函數的單個定義更大。

假設我無法將專業化移動到.cpp文件並將其保留在帶有static .h文件中...

我看不出有什么理由需要,但無論如何......

...或inline ,當這些函數被添加到包含.h文件的每個.cpp文件時,這會導致代碼重復和膨脹在優化版本中,即使它們未被使用?

不,如果它們未在給定文件中使用,則它們不會影響從該文件編譯的對象的大小。

您的問題具有誤導性,因為它似乎與模板有關(標題非常清楚模板!)但是,未使用的內聯/靜態函數是否會導致代碼膨脹與函數是否為模板無關。

如果您的問題只是“未使用的內聯函數和靜態函數會影響對象大小嗎?” 對於正常功能和功能模板,答案是否定的。

應將此類顯式特化移至.cpp文件或inline 鏈接器會在那里找到它們。 如果您在標題中定義它們,您將獲得“已定義”錯誤消息,就像您將獲得多個編譯單元包含的標頭中定義的普通非內聯和非靜態函數一樣。

暫無
暫無

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

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