2016-12-30 43 views
22

當我通過模板函數作爲基類的一個模板參數,鏈接器抱怨說,它不能鏈接函數:錯誤消息「未定義參考作爲模板參數傳遞模板函數」

#include <stdio.h> 

template<int I> inline int identity() {return I;} 
//template<> inline int identity<10>() {return 20;} 

template<int (*fn)()> 
class Base { 
public: 
    int f() { 
     return fn(); 
    } 
}; 

template<int Val> 
class Derived : public Base<identity<10> > { 
public: 
    int f2() { 
     return f(); 
    } 
}; 

int main(int argc, char **argv) { 
    Derived<10> o; 
    printf("result: %d\n", o.f2()); 
    return 0; 
} 

結果:

$ g++ -o test2 test2.cpp && ./test2 
/tmp/ccahIuzY.o: In function `Base<&(int identity<10>())>::f()': 
test2.cpp:(.text._ZN4BaseIXadL_Z8identityILi10EEivEEE1fEv[_ZN4BaseIXadL_Z8identityILi10EEivEEE1fEv]+0xd): undefined reference to `int identity<10>()' 
collect2: error: ld returned 1 exit status 

如果我註釋掉專業化,那麼代碼將按照預期編譯和鏈接。另外,如果我繼承Base<identity<Val> >而不是Base<identity<10> >,則代碼按我的預期工作。

試一下:http://coliru.stacked-crooked.com/a/9fd1c3aae847aaf7

我怎麼錯過?

+3

這個問題似乎是一個gcc的錯誤:它編譯和使用鐺和ICC鏈接確定。順便說一句,名稱_identity()_通常用於轉換,其結果與參數完全相同。 –

+0

@DietmarKühl好吧,'身份()'返回'X'。 :-) – melpomene

+2

解決方法:'派生類:public Base (identity <10>)>'。 [live demo](http://melpon.org/wandbox/permlink/E4aRHqcZaac7vd3C) –

回答

19

看來問題是gcc的一個錯誤:代碼編譯和鏗鏘,國際商會,以及EDG前端的鏈接。一個潛在的變通辦法不改變任何用途將是使用,而不是函數的類模板identity的:

template<int I> 
struct identity { 
    operator int() { return I; } 
}; 

template<typename fn> 
class Base { 
public: 
    int f() { 
     return fn(); 
    } 
}; 
+0

不製作函數模板'inline'也可以。鏈接器是否應該刪除重複的模板實例? – Etherealone