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 am currently running GCC 4.8.

+4
source share
3 answers

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

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

Here's 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 tested this with gcc 4.7.2 and with clang 3.4 (trunk 184647), they work as expected.
Here is the online version of Stacked-Crooked. However, this code does not compile in Ideone. Since I could not figure out the parameters passed to the compiler in Ideone, I abandoned this site.


I shamelessly stole the make_array function from @Pavel Minaev on How to emulate array initialization C "int arr [] = {e1, e2, e3, ...}" with the question std :: array? . Other make_array suggestions caused compilation errors that I could not fix.

This make_array function has limitations, please read the entire post ; specifically a discussion of std :: array - if only he knew its size in comp.lang.C ++. refers to the moderator. Obviously getting a sensible make_array quite difficult. I would not recommend a simple make_array approach in this answer, which will be used in production code.


You will have no problem if the size was a template argument for std::initializer_list . Hence the question Why is size not an argument to the std :: initializer_list template?

+6
source

Apparently not. The standard (14.8.2.5) calls this an irreducible context;

However, in some contexts, the value does not participate in type inference, but instead uses the values โ€‹โ€‹of the template arguments, which were either output elsewhere or explicitly specified.

...

Impossible contexts:

...

  • A function parameter for which the associated argument is a list of initializers (8.5.4), but the parameter does not have std :: initializer_list or a reference to a possible cd-type type std :: initializer_list.

Example:

template <class T> void g (T);
g ({1,2,3}); // error: no argument is output for T

EDIT: you can do the same with std::vector if you just use the initializer_list overload to conclude that type works;

 template<typename T> void foo(const std::vector<T>& src) { ...your code here... } template<typename T> void foo(const std::initializer_list<T>& src) { foo(std::vector<T>(src)); } foo({1,2,3}); // Compiles 

... but, unfortunately, since the size of initializer_list not an argument to the template, I cannot think of a way to infer and redirect the size of the array from initializer_list in the same way as the type.

+3
source

You can use the list of initializers directly to achieve this syntax. eg:.

 #include <iostream> #include <initializer_list> void foo(std::initializer_list<int> il) { for (auto i: il) std::cout << i < std::endl; } int main() { foo({1,2,3}); } 

or make it more general:

 template <typename T> void foo(std::initializer_list<T> il) { ... 
+1
source

Source: https://habr.com/ru/post/1488929/


All Articles