Chcę używać idiomu pimpl, aby uniknąć sytuacji, w której użytkownicy mojej biblioteki potrzebują naszych zewnętrznych zależności (np. Doładowania itp.), Ale kiedy moja klasa jest szablonowana, co wydaje się niemożliwe, ponieważ metody muszą być w nagłówek. Czy jest coś, co mogę zrobić zamiast tego?pimpl dla szablonowej klasy
Odpowiedz
Jeśli klasa jest szablonem, użytkownicy zasadniczo muszą ją skompilować (i jest to dosłownie prawdziwe w najczęściej używanych implementacjach C++) i dlatego potrzebują twoich zewnętrznych zależności.
Najprostszym rozwiązaniem jest umieszczenie większości implementacji klasy w klasie podstawowej bez szablonu (lub zamkniętym elemencie członkowskim jakiejś klasy). Rozwiąż tam problem ukrywania się w module.
Następnie wpisz szablon klasy pochodnej (lub otaczającej), aby dodać do niej bezpieczeństwo typu.
Na przykład, załóżmy, że masz szablon, który zapewnia niesamowitą zdolność do przeznaczenia na pierwszym dostępu (pominięciem koniecznych konstruktor kopiujący, cesja, destructor):
template <class T>
class MyContainer
{
T *instance_;
public:
MyContainer() : instance_(0) {}
T &access()
{
if (instance_ == 0)
instance_ = new T();
return *instance_;
}
};
Jeśli chciał „logika” być podzielone na klasy bazowej bez szablonu, trzeba parametryzacji zachowania w sposób non-szablonu, który jest powiedzieć, jak używać funkcji wirtualna:
class MyBase
{
void *instance_;
virtual void *allocate() = 0;
public:
MyBase() : instance_(0) {}
void *access()
{
if (instance_ == 0)
instance_ = allocate();
return instance_;
}
};
Następnie można dodać typu świadomości w warstwie zewnętrznej:
template <class T>
class MyContainer : MyBase
{
virtual void *allocate()
{ return new T(); }
public:
T &access()
{ return *(reinterpret_cast<T *>(MyBase::access())); }
};
tj. Użytkownik korzysta z funkcji wirtualnych w celu umożliwienia szablonowi "wypełnienia" operacji zależnych od typu. Oczywiście ten wzorzec miałby naprawdę sens tylko wtedy, gdybyś miał jakąś logikę biznesową, wartą wysiłku ukrywania się.
Można jawnie tworzyć instancje szablonów w pliku źródłowym, ale jest to możliwe tylko wtedy, gdy wiesz, jaki będzie typ szablonu. W przeciwnym razie nie używaj idiomu pimpl dla szablonów.
coś takiego:
header.hpp:
#ifndef HEADER_HPP
#define HEADER_HPP
template< typename T >
class A
{
// constructor+methods + pimpl
};
#endif
source.cpp:
#include "header.hpp"
// implementation
// explicitly instantiate for types that will be used
template class A<int>;
template class A<float>;
// etc...
-1 Nie używaj 'auto_ptr' dla PIMPL (jest to ** niezdefiniowane zachowanie ** do tworzenia' auto_ptr' z niekompletnym typem). Działa, jeśli zdefiniujesz zarówno konstruktor, jak i destruktor dla klasy zewnętrznej. Ale w takim przypadku nie potrzebujesz inteligentnego wskaźnika. –
@ AlfP.Steinbach unique_ptr? Czy tylko surowy wskaźnik? –
Tak, oba OK (chociaż nie jestem pewien co do szczegółów użycia 'unique_ptr' w tym przypadku, po prostu użyłbym' shared_ptr' i zaakceptowałbym obciążenie jako koszt niewymagający odczytywania drobnego druku w standard). Pozdrawiam, –
Istnieją dwa główne rozwiązania:
natomiast interfejs zależy od tego ja typ
T
, odradza się do słabiej wpisanej implementacji (np. jeden używający wskaźników bezpośrednio lub wykreślenie typu koryta) lubobsługuje tylko określoną i dość ograniczoną liczbę typów.
Drugie rozwiązanie dotyczy np. char
/wchar_t
- niezależne elementy.
Pierwsze rozwiązanie było dość powszechne we wczesnych dniach szablonów C++, ponieważ w tamtym czasie kompilatory nie były dobre w rozpoznawaniu podobieństw w generowanym kodzie maszynowym, i wprowadzałyby kod “, który rozkwitłby pod numerem ”. Dzisiaj, ku zaskoczeniu każdego nowicjusza, który próbuje go rozwiązać, rozwiązanie szablonowe może często mieć mniejszy ślad kodu maszynowego niż rozwiązanie bazujące na polimorfizmie środowiska wykonawczego. Oczywiście, YMMV.
Cheers & HTH.,
Ktoś próbował edytować, sugerując usunięcie "bezpośrednio lub poprzez usunięcie typu" i "konkretne i ..." kwalifikacja. Opracowanie jest niezbędne dla znaczenia, a kwalifikacja jest konieczna dla poprawności. Obecna odpowiedź "zaakceptuj jako odpowiedź" jest przykładem "bezpośrednio". Nie ma jeszcze przykładu "wymazywania typu", a jedyną wzmianką jest w tej odpowiedzi; byłoby wstydem, gdyby ktoś usunął to. –
- 1. Specjalizacja niekompletna klasy szablonowej
- 2. Jak zaprzyjaźnić się z konstruktorem klasy szablonowej?
- 3. Jak korzystać z unique_ptr dla pimpl?
- 4. Jak mierzyć kandydatów na pimpl?
- 5. Szablon klasy z przyjacielem klasy szablonowej, co tu się naprawdę dzieje?
- 6. Czy to dobre miejsce na wzór PIMPL?
- 7. pimpl-idiom w szablonie; który inteligentny wskaźnik?
- 8. Specjalizacja członka klasy szablonu dla typu szablonu klasy szablonu
- 9. Powtarzanie w szablonowej funkcji po zmianie typu
- 10. Implementowanie kaskadowego wiązania DropDownList w szablonowej kontroli
- 11. Ukryj realizacja za pomocą wskaźnika (Pimpl idiom)
- 12. Dlaczego pimpl powinien być zadeklarowany jako struktura, a nie klasa?
- 13. Ukrywanie szablonowej funkcji helpera - statyczne elementy lub nienazwana przestrzeń nazw
- 14. Zmienna licznika dla klasy
- 15. anonimowe klasy wewnętrzne dla przycisków
- 16. python - wsparcie .send() dla klasy?
- 17. Struktura klasy dla listy Klasa?
- 18. Java hashCode dla klasy Point
- 19. Zastępowanie metoda __contains__ dla klasy
- 20. Delegat Swift dla ogólnej klasy
- 21. Serializacja Java dla rozszerzonej klasy
- 22. filtr rynku dla klasy pamięci
- 23. Typ klasy Haskella dla kolejki
- 24. nadpisywanie bool() dla niestandardowej klasy
- 25. Definiowanie aliasu dla klasy Razor
- 26. Zastąp nazwę klasy dla XmlSerialization
- 27. Szablon klasy dla typów liczbowych
- 28. Ustaw folder dla ścieżki klasy
- 29. Niestandardowe atrybuty dla członków klasy
- 30. Odpowiedni wzorzec dla klasy ActiveRecord
myślę, że to podejście może być również przydatna, jeśli nie chcesz, aby Twoje definicje preprocesora ('# define'), stałe itd., Aby były widoczne. Jako programista nie chcę widzieć szczegółów implementacji klasy/biblioteki, której używam, szczególnie na liście autouzupełniania. Możesz je ukryć, nawet jeśli twoja logika biznesowa jest niegodna ukrywania się. – mostruash