Search code examples
c++templatesc++11initializer-list

C++11 Implicit conversion from initialization list to array parameter


In C++11, is it possible to do something similar to the following?

template<typename T, size_t N>
void foo(array<T, N> src) { ... }

...

foo({1, 2, 3})

I'm currently running GCC 4.8.


Solution

  • Yes, I managed to get the following work (since you allow something similar):

    template<typename T, size_t N>
    void foo(array<T, N> src) { ... }
    
    ...
    
    foo('a', 'b');
    foo(1, 2, 3);
    

    Here is how:

    #include <array>
    #include <iostream>
    #include <utility>
    using namespace std;
    
    template<typename T, unsigned long N>
    void foo(array<T,N> src) { 
    
      for (auto e : src)
        cout << e << endl;
    }
    
    template<class T, class... Tail>
    auto make_array(T head, Tail... tail) -> std::array<T, 1 + sizeof...(Tail)>
    {
         std::array<T, 1 + sizeof...(Tail)> a = {{ head, tail ... }};
         return a;
    }
    
    template<class T, class... Tail> 
    void foo(T&& head, Tail&&... values) {
    
        foo(make_array(std::forward<T>(head), std::forward<Tail>(values)...));
    }
    
    int main() {
    
      foo('a', 'b');
    
      foo(1, 2, 3);
    }
    

    I have tested this with gcc 4.7.2 and with clang 3.4 (trunk 184647), they work as expected.
    Here is an online version at Stacked-Crooked. However, this code fails to compile at Ideone. Since I was unable to figure out the options passed to the compiler at Ideone, I've given up on that site.


    I have shamelessly stolen the make_array function from @Pavel Minaev's answer to the How to emulate C array initialization “int arr[] = { e1, e2, e3, … }” behaviour with std::array? question. The other make_array suggestions caused compile errors that I couldn't fix.

    This make_array function has limitations, please read the entire post; in particular the discussion std::array - if only it knew its size on comp.lang.c++.moderated is referenced. Apparently, getting a reasonable make_array is quite tricky. I wouldn't recommend the simple-minded make_array in this answer to be used in production code.


    You wouldn't have any problems if the size was a template argument to std::initializer_list. Hence the question Why is the size not a template argument of std::initializer_list?