7

If this is a duplicate I apologize. I looked around and found similar issues but nothing exactly like this.

If I instantiate a template like so...

MyClass<int[10]> c;

How can I write the template to get access to both the type and the array size? I've tried everything I can think of and I can't get it.

I was inspired by the std::function template which lets you use similar syntax to the function prototype, like...

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

So I thought it would be nice to have something similar for the array and its size. I can use any of the newest c++ features (c++ 11/14).

extracrispy
  • 669
  • 5
  • 16
  • 1
    Why don't you use `std::array`? It's awesome and you should use it ;-) – stefan Jun 01 '15 at 15:24
  • @stefan: Well, I'm trying to add some contextual syntactic sugar to a class of mine. It has nothing to do with me using actual arrays. – extracrispy Jun 01 '15 at 15:26
  • Is that syntax the only valid use of your class, or is it a special case ? – Quentin Jun 01 '15 at 15:26
  • you should take care of some pitfalls when you do http://stackoverflow.com/questions/28243371/why-does-pointer-decay-take-priority-over-a-deduced-template – bolov Jun 01 '15 at 15:41
  • 1
    Instead of writing your own metafunctions to extract the element type and array size, you could use `std::extent` and `std::remove_extent`. – dyp Jun 01 '15 at 17:13

3 Answers3

18

You can add a partial specialization which looks like this:

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

Here's a demo.

Pradhan
  • 16,391
  • 3
  • 44
  • 59
  • 1
    Beautiful! Thank you. I was having such a hard time with the syntax I couldn't get anything working. – extracrispy Jun 01 '15 at 15:34
  • 2
    @Pradhan: `int` instead of `size_t` may *look* like poor style to some poor soul who is sufficiently unsure that he (it's inevitably a he) doesn't want to state or stand by his, well, impression. That said, at least some old versions of g++ had a bug which effectively required you to use `size_t`. I would use a size type defined as `ptrdiff_t`. – Cheers and hth. - Alf Jun 01 '15 at 15:35
  • @Cheersandhth.-Alf Thanks! Updated the answer, but I am unable to find the relevant gcc bug report. – Pradhan Jun 01 '15 at 15:43
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;};

now you can array_size<ArrType>{} and array_element_t<ArrType> without unpacking the type.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
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);
};
user1095108
  • 14,119
  • 9
  • 58
  • 116