2009-11-05 7 views
21

Jest to minimalny przypadek testowy kodu, który faktycznie mam. To nie kiedy próbuje ocenić a.getResult<B>():Szablony: funkcja szablonu nie gra dobrze z funkcją elementu szablonu klasy

test.cpp: In function 'void printStuff(const A&)': 
test.cpp:6: error: expected primary-expression before '>' token 
test.cpp:6: error: expected primary-expression before ')' token 

Kod jest:

#include <iostream> 

template< class A, class B> 
void printStuff(const A& a) 
{ 
    size_t value = a.getResult<B>(); 
    std::cout << value << std::endl; 
} 

struct Firstclass { 
    template< class X > 
    size_t getResult() const { 
     X someInstance; 
     return sizeof(someInstance); 
    } 
}; 

int main(int, char**) { 
    Firstclass foo; 

    printStuff<Firstclass, short int>(foo); 
    printStuff<Firstclass, double>(foo); 

    std::cout << foo.getResult<double>() << std::endl; 

    return 0; 
} 

Gdybym wykomentuj funkcję printStuff i gdzie to się nazywa, wywołanie foo.getResult<double>() kompiluje dobrze i robi to, co ma.

Każdy pomysł, co się dzieje? Od jakiegoś czasu pracuję z obszernie szablonowym kodem i nigdy nie spotkałem się z niczym podobnym.

Odpowiedz

35

Po odesłaniu do szablonu należącego do typu zależnego należy poprzedzić go słowem kluczowym template. Jest to jak wezwanie do getResult wewnątrz printStuff powinien wyglądać

size_t value = a.template getResult<B>(); 

ten jest podobny do za pomocą słowa kluczowego typename odnosząc się do zagnieżdżonych typenames w rodzaju zależnej. Z jakiegoś powodu bit o numerze typename z typami zagnieżdżonymi jest raczej dobrze znany, ale podobny wymóg dla template z szablonami zagnieżdżonymi jest stosunkowo mało znany.

Należy pamiętać, że ogólna struktura składni jest nieco inna. typename jest zawsze umieszczany przed pełną nazwą typu, natomiast template jest wstawiany w środku.

Ponownie, jest to konieczne tylko jeśli dostęp człon szablon zależną od rodzaju, który w powyższym przykładzie byłby A w printStuff. Podczas wywoływania foo.getResult<> w main typ foo nie jest zależny, więc nie ma potrzeby dodawania słowa kluczowego template.

+7

Wow, właśnie ja, kiedy myślałam, że znam wszystko było wiedzieć o C++ ... –

+6

Dzięki! To najbardziej dziwna składnia, jaką widziałem w C++. –

+3

W jakiś sposób VC++ jest dość łagodny (tzn. Często można uciec bez niego), ale gcc zdecydowanie nie jest! –

8

kod jest źle sformułowane zgodnie z C++ standard 14,2/4:

Kiedy nazwa specjalizacji szablonu element pojawia się po . lub -> w postfix ekspresji lub po nested- Specyfikator nazwy w kwalifikowanym identyfikatorze , a wyrażenie przyrostkowe lub kwalifikowany identyfikator jawnie zależy od parametru szablonu (14.6.2), nazwa szablonu elementu członkowskiego musi być poprzedzona prefiksem słowa kluczowego template. W przeciwnym razie przyjmuje się, że nazwa nie jest szablonem.

Więc trzeba napisać size_t value = a.template getResult<B>();

Powiązane problemy