2016-10-17 32 views
5

Wdrażam coś bardzo podobnego do std::vector, ale używa tablicy na stosie zamiast alokowania pamięci.sfinae away a destructor

D-tor wywołuje funkcję używającą SFINAE.

  • Jeśli value_type jest POD, funkcja ma puste ciało.
  • Jeśli jest normalną klasą, taką jak std::string, funkcja ma treść i poprawnie niszczy wszystkie dane.

Teraz chcę móc używać tego nowego std::vector jako constexpr. Jednak nawet c-tor jest zadeklarowany jako constexpr, kod nie kompiluje się, ponieważ klasa ma nietrywialny d-tor.

Oto niewielki fragment kodu:

template<typename T, std::size_t SIZE> 
class SmallVector{ 
    constexpr SmallVector() = default; 

    ~SmallVector(){ 
     destructAll_<value_type>(); 
    } 

    // ... 

    template<typename X> 
    typename std::enable_if<std::is_trivially_destructible<X>::value == true>::type 
    destructAll_() noexcept{ 
    } 

}; 

Czy mogę coś zrobić, aby klasa być constexpr jeśli value_type jest POD i utrzymywanie funkcjonalności dla typów danych non POD.
(Nie w tym samym czasie oczywiście)

+2

bym zamiast dziedziczyć 'SmallVectorImpl :: wartości>' które będą miały główny definicji i specjalizacji dla trywialnie zniszczalne typów. Jedyna różnica między nimi to destruktor. – DeiDei

+0

Mój pomysł jest podobny - jedna czyta tylko klasę bazową i wszystkie metody mutowania w dwóch dziedziczonych wersjach. Czy możesz też odpowiedzieć na swój pomysł, ponieważ nie widzę, jak pomaga trzeci element "komponentu". masz na myśli dziedziczenie z dwóch klas bazowych? – Nick

+0

Jak bardzo podobny do 'std :: vector' może być taki typ? Czy raczej reimplementujesz 'std :: array'? Orrrr to wektor z ogromną macierzą auto-storage i wieloma miejscami docelowymi nowymi? :) –

Odpowiedz

5

Niestety, nie ma sposobu, aby włączyć/wyłączyć destruktor z SFINAE, ani z przyszłymi koncepcjami. To dlatego destructos:

  • nie można matrycy
  • nie może mieć argumentów
  • nie może mieć typ zwracany

Co można zrobić, to Specjalizujemy całą klasę, lub jeszcze lepiej, stwórz klasę bazową, która zawiera tylko konstrukt/destruct i podstawowy dostęp i specjalizuj się w tym.

template <class T, class Enable = void> 
struct X { 
    ~X() {} 
}; 

template <class T> 
struct X<T, std::enable_if_t<std::is_pod<T>::value>> { 
}; 

static_assert(std::is_trivially_destructible<X<int>>::value); 
static_assert(!std::is_trivially_destructible<X<std::vector<int>>>::value);