2010-09-04 15 views
20

Dlaczego to się nie kompiluje? (G ++ - 4,5)adres funkcji szablonu C++

template < typename U > 
static void h() { 
} 

int main() { 
    auto p = &h<int>; // error: p has incomplete type 
} 

EDIT: Oto obejście:

template < typename U > 
static void h() { 
} 

int main() { 
    typedef decltype (&h<int>) D; 
    D p = &h<int>; // works 
} 
+1

Kompiluje dobrze na Visual Studio 2010. Jest to najprawdopodobniej usterka w GCC. To, co możesz spróbować, to 'decltype (& h ) p = & h ;' – Puppy

+0

Działa przynajmniej z G ++ 4.6. – Maister

+0

@DeadMG: Bez "auto" nie ma nawet potrzeby pisania na klawiaturze, 'void (* p)() = & h ;' również się skompiluje. – doc

Odpowiedz

13

w C++ 0x to jest gwarantowane do pracy. Jednak w C++ 03 to nie działało (część inicjalizacyjna, to znaczy) i niektóre kompilatory najwyraźniej jeszcze go nie obsługują.

Co więcej, pamiętam, że napisy w C++ 0x nie są jasne, co dzieje się z &h<int>, gdy jest to argument do szablonu funkcji i wyprowadza się odpowiedni parametr (to jest to, do czego auto jest tłumaczone, koncepcyjnie). Chodzi jednak o to, aby była ona ważna. Zobacz this defect report, gdzie zaprojektowali oni tekst, przykład "Nico Josuttis" i ich ostateczny przykład.

Istnieje inna zasada, która wymusza stosowanie sformułowania, ale kompilatory nie implementują poprawnie. Na przykład see this clang PR.

0

To nie kompiluje ponieważ typu 'p' nie jest znany kompilator, który jest koniecznością w C++, w przeciwieństwie do niektórych innych języków.

Spróbuj

template < typename U > 
static void h() { 
} 

int main() { 
    auto void (*p)() = &h<int>; 
} 
+1

Słowo kluczowe 'auto' służy do automatycznego odliczania typów. Funkcja C++ 0x. – dirkgently

+0

OK, ale w moim prawdziwym kodzie h ma wiele innych parametrów w zależności od U i innych szablonów i nie chcę ich wszystkich określać, ponieważ typ p powinien być znany kompilatorowi. – Thomas

+1

@dirkgenly: Oh. Nadal jestem w C++ 03, gdzie "auto" jest dla zmiennych automatycznych – Chubsdad

0

Spróbuj

auto p = static_cast<void(*)()>(& h<int>); 

Ponieważ gcc traktuje funkcję jak przeciążony jednej matrycy. Z punktu widzenia gcc jest tak, jakbyś miał h(int param) i h(float param) - który z kompilatorów musi wybrać?

Zauważyłem, jaki był problem w starszych wersjach gcc, ale spróbuję wyjaśnić to dokładniej. GCC nie mógł wydedukować typu, ponieważ funkcja szablonowa była traktowana jak przeciążona. To było w zasadzie jak to masz następujące elementy:

void h(int) 
{ 
} 

void h(float) 
{ 
} 

void (*p)(int) = & h; //ok 
void (*p)(float) = & h; //ok 
auto p = & h; //error: which version of h? 

Dla gcc h<int> było jak przeciążony h funkcji z niekończącymi alternatyw zależności T parametru. Z podanym kodem był O.K. aby wykonać następujące czynności:

void (*p)() = & h<int>; 

(dlatego ja nie dostać typedefed „obejście”)

Tak jak myślałem OP chciał użyć C++ 11 auto hasła jak sugeruje znacznika, Statycznie odlewałem h<int> na void(*)(), co jest rodzajem braku operacji, po to tylko, aby oszukać gcc, ponieważ nie było w stanie poprawnie obsłużyć funkcji szablonów i nie było możliwe.

Funkcje void h<int>() i void h<float>() powinny być oczywiście traktowane jak różne funkcje za pomocą tego samego typu wskaźnika, a nie przeciążać wersji funkcji h.Gdy instancja powinni zachowywać się jak void hInt() i void hFloat() i powinieneś być w stanie wykorzystać auto jak tutaj:

void hInt() 
{ 
} 

void hFloat() 
{ 
} 

auto p = hInt; 
p = hFloat; 

Ale z jakiegoś powodu dla gcc byli jak przeciążonych wersji h.

Podaj powód do odrzucenia.

+0

Nie jestem downvoter :) W każdym razie nie jestem pewien, aby zrozumieć swoją logikę: skoro jesteś static_casting do czasu kompilacji znanego typu, jaki jest pożytek z auto? – Francesco

+0

@Francesco: bez rzutowania gcc zgłasza błąd "Instrukcja nie może rozwiązać adresu przeciążonej funkcji". Otrzymasz ten sam błąd w przypadku przeciążonej funkcji (np. 'Void h (int)' i 'void h (float)'), w którym to przypadku kompilator nie jest w stanie określić, którą wersję wybrać, kiedy znajdzie instrukcję '& h' . Z jakiegoś powodu (myślę, że to coś z odkryciem argumentów w szablonach) funkcja szablonowa traktowana jest w taki sam sposób jak przeciążony. Po tym jak użyłem static_cast jak w przypadku przeciążonych funkcji, zaczęło się kompilacja. 'auto' jest używane do wyprowadzenia typu' p'. – doc

+0

@Francesco: otrzymali taki sam wynik z 'typedef' jak z static_cast. Myślałem, że chce C++ 0x 'auto' słowo kluczowe ... – doc

Powiązane problemy