2016-12-30 44 views
22

Kiedy mijam funkcji szablonu jako parametr szablonu z klasy bazowej, łącznik narzeka, że ​​nie można łączyć funkcji:Komunikat o błędzie „niezdefiniowana odniesienia do funkcji szablonu przekazanego jako parametr szablonu”

#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; 
} 

Skutkuje :

$ 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 

Jeśli skomentuję specjalizację, kod kompiluje i łączy zgodnie z oczekiwaniami. Ponadto, jeśli dziedziczy po Base<identity<Val> > zamiast Base<identity<10> >, kod działa tak, jak oczekuję.

Spróbuj tutaj: http://coliru.stacked-crooked.com/a/9fd1c3aae847aaf7

Czego brakuje?

+3

Problem ten wydaje się być gcc bug: kompiluje i łączy OK za pomocą szczęk i ICC. BTW, nazwa _identity() _ jest zwykle używana do transformacji, gdy wynik jest identyczny z argumentem. –

+0

@ DietmarKühl No cóż, 'identity ()' zwraca 'X'. :-) – melpomene

+2

Sposób obejścia: 'klasa Pochodna: publiczna baza (tożsamość <10>)>'. [live demo] (http://melpon.org/wandbox/permlink/E4aRHqcZaac7vd3C) –

Odpowiedz

19

Wydaje się, że problemem jest gcc błąd: kod kompiluje i powiązania z brzękiem, MTK, oraz nakładka EDG. Potencjalny obejście nie zmienia jakichkolwiek zastosowań byłoby użycie klasy szablonu identity zamiast funkcji:

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

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

Nie można również utworzyć szablonu funkcji 'inline'. Czy linker nie powinien mimo wszystko usunąć zduplikowanych instancji szablonów? – Etherealone