2011-07-18 10 views
6

W odpowiedzi na pytanie this natknąłem się na tę różnicę w zachowaniu w odniesieniu do tworzenia szablonu.Jakie są zasady dotyczące tworzenia wystąpień typów szablonów (klasa/funkcja) podczas przyjmowania adresu?

Początkowo jest szablonem funkcji

template <typename T> void my_callback(void* data) { … } 

Teraz coś wymaga adres to - konkretnie void*, więc oczywistym rozwiązaniem jest

bar(reinterpret_cast<void*>(&my_callback<int>)); 

Jednak z wersji kompilatora pre gcc 4.5, to kończy się niepowodzeniem z niewystarczającym kontekstem ... błędu. Drobne - więc poprawka ma najpierw "odlać", co wymusza utworzenie, tj .:

void (*callback)(void*) = my_callback<int>; 
bar(reinterpret_cast<void*>(callback)); 

To działa dobrze.

Teraz drugi scenariusz, zamiast bycia wolną funkcję, to statyczne członek szablonu klasy, tj

template <typename T> 
struct foo 
{ 
    static void my_callback(void* data) { 
    T& x = *static_cast<T*>(data); 
    std:: cout << "Call[T] with " << x << std::endl; 
    } 
}; 

Teraz, oryginalny reinterpret_cast działa dobrze.

bar(reinterpret_cast<void*>(&foo<int>::my_callback)); 

Moje pytanie brzmi - dlaczego ta widoczna różnica w zachowaniu?

+0

lol ... zapożyczam z dość niedawnego pytania, które widzę :) +1, pytanie jest rzeczywiście interesujące. –

Odpowiedz

2

Od n3290, 14.7.1 niejawny instancji [temp.inst]

2 O ile specjalizacja szablonu funkcja została wyraźnie instancja lub wyraźnie wyspecjalizowane, specjalizacja szablonu funkcja jest niejawnie, gdy instancja jest specjalizacja odwołuje się w kontekście, który wymaga istnienia definicji funkcji.

W punkcie 1 istnieją podobne zasady dotyczące specjalizacji szablonów klas. Zauważ, że Standard mówi w kategoriach specjalizacji, ponieważ specjalizacja jest domyślnie zadeklarowana, gdy używany jest szablon, tutaj nie ma specjalności dostarczanej przez użytkownika, przynajmniej w przypadku szablonów funkcji (paragraf 8).

połączeniu z pkt 10,

10 Implementacja nie niejawnie instancji funkcja szablonu, szablon członkowskim, funkcji składowej zakaz wirtualną klasę członkiem lub statyczny element danych na poziomie szablon klasy, który nie wymaga utworzenia instancji .

Myślę, że zasada brzmi: jak tylko obiekt/klasa członek/lub funkcja jest potrzebna, aby program działa inaczej (mówiąc nieformalnie), szablon jest domyślnie instancja ale nie wcześniej. Obejmuje to przyjmowanie adresu funkcji.

Co do pytania, które powiązane, niektóre zastosowania reinterpret_cast może uczynić program non-conformant, przez które razem jest to bez znaczenia dla wspomnieć dawałaby - I invite you to see my answer there < /bezwstydny>.

+0

tak więc, aby wziąć adres członka (nawet statycznego), typ musi być utworzony - więc kompilator będzie, ale nie dla wolnej funkcji, ponieważ nie musi ... thx. – Nim

+1

@Nim: Uzyskanie adresu funkcji wymaga definicji funkcji (z której linker uzyska adres), więc uzyskanie adresu funkcji szablonu powinno implikować zainicjowanie tej konkretnej specjalizacji funkcji. –

+0

@ David, tak, dlatego zapytałem, dlaczego reinterpret_cast adresu nie działa dla szablonu funkcji, tbh, nie próbowałem wersji pośredniej, jak w odpowiedzi Luc jeszcze. – Nim

Powiązane problemy