2011-01-03 13 views
6

Poniższy kod działa dla mnie:szablony użytkownika funkcyjną i przeciążanie operatorów() w C++

class Foo { 
public: 
    template <class T> T& get() { ... } 
}; 

Foo foo; 
foo.get<int>() = ...; 

jednak następujący fragment kodu nie działa dla mnie:

class Foo { 
public: 
    template <class T> T& operator()() { ... } 
}; 

Foo foo; 
foo<int>() = ...; 

błędów są:

expected primary-expression before '>' token 
expected primary expression before ')' token 

Oba błędy odnoszą się do foo<int>()

Dlaczego to nie działa i czy można to naprawić?

+1

Twój szablon 'operator()' jest całkiem niezdatny do użytku, ponieważ jego wystąpienia mogłyby zostać przeciążone tylko na wartości zwracanej. Kontynuuj używanie nazwy 'get' lub podobnej. – aschepler

+0

Nie nadaje się do użytku (choć może nie być preferowana). Zobacz odpowiedzi poniżej. –

+0

Dlaczego zmieniasz funkcje, ale nie całą klasę? –

Odpowiedz

10

Jeśli trzeba wyraźnie określić argument szablonu, trzeba by użyć składni operator:

foo.operator()<int>() 

Nie jest jakiś sposób, aby podać argumenty za pomocą składni funkcji wywołanie. Jeśli nie możesz wywnioskować argumentów szablonu z argumentów funkcji, lepiej użyć funkcji składowej niż przeciążenia operatora.

+0

Ahh, w istocie, dzięki. Ma to sens teraz. – Dan

-1

Ewentualnie można zrobić

class Foo { 
public: 
    template <class T> operator T&() { ... } 
}; 

Następnie zostanie ona automatycznie wywołać właściwą funkcję w zależności od „powrót” typu:

Foo foo; 
int i=foo; 

wiem, że większość ludzi nie lubi tego, jak funkcja, która jest wywoływana, zależy od typu zwracanego, ale uważam, że jest to świetna "sztuczka", która często czyści składnię.

+3

Dodatkowe ostrzeżenie: łatwo będzie przypadkowo utworzyć tę metodę "konwersji" z niezamierzonym typem. – aschepler

+2

Myślę, że jest to sztuczka, która nadmiernie komplikuje kod. Podałeś operatora konwersji dla * dowolnego * typu ... uderzy cię w najbardziej nieprawdopodobny z miejsc, w których nie możesz się spodziewać ani nawet go zrealizować! –

1

Problem polega na tym, że lista parametrów szablonu znajduje się w niewłaściwym miejscu; to tak, jakbyś próbował użyć obiektu lub funkcji o nazwie foo z argumentem szablonu int, ale w rzeczywistości jest to operator(), który chcesz włączyć listę parametrów szablonu.

Niestety (prawdopodobnie przynajmniej), nie ma sposobu obejścia tego z operatorami. Musisz nazwać je pełnymi funkcjami:

class Foo { 
public: 
    template <class T> T& operator()() { ... } 
}; 

Foo foo; 
foo.operator()<int> = ...; 

Mam nadzieję, że to pomoże.