2009-10-08 24 views
10

Czy istnieje częściowa specjalizacja dla metody klasy szablonów?Specjalizacja metodą częściową C++

template <class A, class B> 
class C 
{ 
    void foo(); 
} 

nie działa specjalizować się to tak:

template <class A> void C<A, CObject>::foo() {}; 

Każda pomoc?

+0

Istnieje kilka sposobów pokazanych w innych odpowiedziach: http://stackoverflow.com/questions/1501357/template-specialization-of-particular-members/1501455#1501455 –

Odpowiedz

11

Jeśli już wyspecjalizowane klasy można podać inną realizację foo w wyspecjalizowanych zajęć:

template<typename A, typename B> 
class C 
{ 
public: 
    void foo() { cout << "default" << endl; }; 
}; 

template<typename A> 
class C<A, CObject> 
{ 
public: 
    void foo() { cout << "CObject" << endl; }; 
}; 

specjalizować funkcję składową w Visual C++ 2008 można zrobić to szablon też:

template<typename A, typename B> 
class C 
{ 
    template<typename T> 
    void foo(); 

    template<> 
    void foo<CObject>(); 
}; 

Powyższe rozwiązanie wydaje się być dostępne tylko w przyszłym standardzie C++ (zgodnie z projektem nr 2914 14.6.5.3/2).

+0

Podczas gdy druga jest prawidłowa, pierwsza jest błędna - nie możesz umieścić wyraźnych specjalizacji w zakresie klasy - i nawet jeśli umieścisz specjalizację szablonu w zakresie przestrzeni nazw - jeśli specjalizujesz szablon, wszystkie jego szablony otaczające muszą być wyspecjalizowane też :(Więc musisz trzymać się drugiej drogi: –

+0

Tak więc to nie zadziała na przykład: 'szablon szablon <> void C :: foo () {}', ponieważ podczas szablon funkcji członka jest wyspecjalizowany, zewnętrzny nie jest jeszcze. Można zrobić odwrotnie, chociaż 'template <> szablon void C :: foo() {}' ale podejrzewam, że to nie jest to czego chce do zrobienia -.- –

+0

Najpierw wydaje się, że nie jest to C++ 03 Zgodny ze standardami, ale działa w Visual C++ 2008. Wygląda jak rozszerzenie C++ 0x (14.6.5.3 Członkowie klasy szablon specia lizacje). –

1

Ponieważ klasa jest szablon, trzeba się specjalizować, że:

template <class A> 
class C<A, CObject> 
{ 
    void foo() { ... } 
} 
+0

Już specjalizuję się w klasie, ale dokładnie muszę specialize method :) – faya

0

Jeśli dobrze pamiętam, nie można dokonać częściowej specjalizacji szablonu dla funkcji. Nie jestem pewien, czy jest on włączony w C++ 0X

Aktualizacja: (Oczekiwanie na potwierdzenie) Jak zauważył w komentarzach, częściowa specjalizacja szablonu funkcji jest możliwe w C++ 0x.

+0

To ograniczenie jest zniesione na C++ 0x –

+0

@yngvedh, czy masz referencję do tego "Aktualizacji:" Uwaga? Jeszcze o tym nie słyszałem. Afaik, po prostu podnoszą domyślne argumenty - tzn. Możesz mieć domyślne argumenty w szablonach funkcji. –

+0

@libt, bez odniesienia. Po prostu założyłem, że the_drow wiedział o czym mówi, ponieważ nie jestem ekspertem od C++ 0X. Czy ktokolwiek z tych osób może to potwierdzić? Zaktualizuję odpowiednio. –

8

Myślę, że jest tam nieporozumienie.

Istnieją dwa rodzaje szablonów:

  • klasy szablon
  • Metody szablon

w przykładzie, masz klasę szablonu, który oczywiście zawiera kilka metod. W takim przypadku będziesz musiał wyspecjalizować klasę.

template <class A> 
class C<A,CObject> 
{ 
    void foo() { ... } // specialized code 
}; 

Problem w przykładzie jest stosunkowo prosta: zdefiniować foo metodę specjalizacji C, ale to nigdy nie było specjalizacji oświadczył wcześniej.

Problem polega na tym, że musisz w pełni wyspecjalizować swoją klasę C (a tym samym skopiować wiele danych). Istnieje kilka obejść.

  • Dziedziczenie (kompozycja?): wykonaj wszystkie typowe prace w klasie bazowej, a następnie przejmuj i klasyfikuj klasę C
  • Przyjaciel: zamiast używać metody "foo" będącej członkiem C, zdefiniuj ją jako funkcję przyjazną dla znajomych i specjalizuj się tylko ta metoda
  • Delegacja: mieć swój „foo” metoda wywołania innej metody „bar”, która jest bezpłatna funkcja, i specjalizują „bar” odpowiednio

które w kod daje:

// 1- Inheritance 
template <class A, class B> 
class CBase 
{ 
    // Everything that does not require specialization 
}; 

template <class A, class B> 
class C: public CBase<A,B> 
     // depending on your need, consider using another inheritance 
     // or even better, composition 
{ 
    void foo(); // generic 
}; 

template <class A> 
class C<A,CObject> : public CBase<A,CObject> 
{ 
    void foo(); // specialized 
}; 

// 2- Friend 
// note the change in signature: 
// - now you need to pass the attributes to be changed 
// - the last parameter helps differentiating the overload 
// as there is no specialization for functions 
template <class A, class B> void foo(Arg1&, Arg2&, const B&); 
template <class A> void foo(Arg1&, Arg2&, const CObject&); 

template <class A, class B> 
class C 
{ 
    friend template <class, class> foo; 
}; 

// 3- Delegation 
// same signature as foo in (2) 
template <class A, class B> void bar(Arg1&, Arg2&, const B&); 
template <class A> void bar(Arg1&, Arg2&, const CObject&); 

template <class A, class B> 
class C 
{ 
    void foo() { bar(member1, member2, B()); } 
}; 

Mam nadzieję, że to wyjaśni i pomoże!

2

Nie, nie ma częściowej specjalizacji szablonu funkcji w C++ 0x do dodania.

Jak słusznie wspomniano powyżej, w odniesieniu do szablonów funkcyjnych zasadniczo 2 rzeczy zostały zrobione:

  • argumenty domyślnym szablonie zostały udostępnione;
  • zostały wprowadzone szablony variadyczne.

Wcześniejsze obejścia powinny być stosowane do "emulowania" specjalizacji szablonów funkcji cząstkowych.

Powiązane problemy