2015-06-01 4 views
7

Jeśli jest to duplikat, przepraszam. Rozejrzałem się i znalazłem podobne problemy, ale nic tak dokładnie nie wyglądało.Czy można wyodrębnić rozmiar tablicy z argumentu szablonu?

Gdybym instancji szablonu jak tak ...

MyClass<int[10]> c; 

Jak mogę napisać szablon, aby uzyskać dostęp zarówno do rodzaju i rozmiaru tablicy? Próbowałem wszystkiego, co mogę wymyślić i nie mogę tego dostać.

I była inspirowana przez szablon std :: function, która pozwala na korzystanie z podobną składnię do prototypu funkcji, jak ...

std::function<int(MyClass&)> myfunc; 

Więc pomyślałem, że byłoby miło mieć coś podobnego do tablicy i jego rozmiar. Mogę używać dowolnej z najnowszych funkcji C++ (C++ 11/14).

+1

Dlaczego nie używasz 'std :: array '? Jest niesamowity i powinieneś go używać ;-) – stefan

+0

@stefan: Cóż, próbuję dodać kontekstualny cukier syntaktyczny do mojej klasy. Nie ma nic wspólnego ze mną przy użyciu rzeczywistych tablic. – extracrispy

+0

Czy ta składnia jest jedynym ważnym zastosowaniem twojej klasy, czy jest to specjalny przypadek? – Quentin

Odpowiedz

17

Możesz dodać częściową specjalizację, która wygląda tak:

template <typename T, ptrdiff_t N> 
class MyClass<T[N]> 
{ 
}; 

Oto demo.

+3

Downvoter, jaki jest problem z tym fragmentem? – Pradhan

+0

Wygląda dobrze dla mnie. – Quentin

+1

Piękne! Dziękuję Ci. Miałem tak trudny czas ze składnią, że nie mogłem nic zrobić. – extracrispy

2
template <typename T, typename = void> 
struct deduce 
{ 
}; 

template <typename T> 
struct deduce<T, 
    typename ::std::enable_if< 
    ::std::is_array<T>{} 
    >::type 
> 
{ 
    using value_type = 
    typename ::std::decay<decltype(::std::declval<T>()[0])>::type; 

    static constexpr auto size = sizeof(T)/sizeof(value_type); 
}; 
+0

Czy to nie jest kompletna przesada? – Quentin

+3

Tak, tylko dla niektórych odmian. – user1095108

+3

"Overkill for variety". Podoba mi się to: p – Quentin

3
template<class Arr> 
struct array_size {}; 
template<class T, size_t N> 
struct array_size<T[N]>:std::integral_constant<std::size_t, N>{}; 
template<class Arr> 
struct array_element {}; 
template<class Arr> 
using array_element_t = typename array_element<Arr>::type; 
template<class T, size_t N> 
struct array_element<T[N]>{using type=T;}; 

teraz możesz array_size<ArrType>{} i array_element_t<ArrType> bez rozpakowywania typ.