Search code examples
c++c++11templatesvariadic-templatesstdarray

array length deduction from argument


Given a function with the parameter signature std::array<const size_t, V> shape like:

template<int V>
struct Cls {int val(){return V;} };


template <int V>
auto make(std::array<const size_t, V> shape) -> Cls<V>{
  return Cls<V>();
}

I need to always add the template parameter V like

auto t1 = make<2>({2, 3}); // does work but need the information twice
std::cout << t1.val() << std::endl;

as the braced-initializer list seems to be casted into a c++11 std::array. However, this seems to me redundant. The length of {2, 3} is two. I know it and the compiler should also know it. Is it possible to wrap it into:

// auto t0 = make({2, 3}); // doesn't work
// auto t0 = make(2, 3); // would be also ok

I tried something like determining the size of the std::array as a constexpr. But I can't get rid of the template argument <2>.

template <int V>
constexpr size_t arr_len(std::array<const size_t, V>){return V;}

template <typename V>
auto make2(V shape) -> Cls<arr_len(shape)>{
  return Cls<arr_len(shape)>();
}

I add a runnable MWE here:

https://ideone.com/wrVe9M

This thread seems to be related but I do not see how it might help. Any suggestions?


Solution

  • I suppose you can use a variadic make() function (make0() in the following example) that can calculate the size as sizeof...(Is)

    The following is a full working example

    #include <array>
    #include <iostream>
    
    
    template<int V>
    struct Cls {int val(){return V;} };
    
    
    template <int V>
    auto make(std::array<const size_t, V> shape) -> Cls<V>{
      return Cls<V>();
    }
    
    template <typename ... Is>
    auto make0 (Is ... is) -> Cls<sizeof...(Is)>
     { return make<sizeof...(Is)>({ {std::size_t(is)... } }); }
    
    int main ()
     {
       auto t1 = make0(2, 3, 5, 7);
    
       std::cout << t1.val() << std::endl;
     }