A convenient way of creating a std::array
Update1: The original title of this post was "A convenient constructor for std::array" but it was brought to my attention that this is a bad name. Therefore this post now describes a convenient way of creating a std::array. Thanks to @jonkalb and @fallingfrombed and @marshall from the C++ slack channel who were the first to provide this valuable feedback
Update2: I was not very surprised about the hint, I think by Arne Mertz on cpp slack, that this solution already exists in TR2. This is great; the implementation in TR2 is of course much more advanced than what I have written. Having a place where I can borrow this implementation from is of course my preferred way. I am very aware of the fact that there are many people out there whose implementation of such functions are in general more advanced and better than my version.
Constructing std::array
I like and use std::array a lot. But every time I use it and have to declare one, I thought that’s a bit too much text to write. And why do I have to tell the compiler the type since it’s known because it’s there?
A short example to illustrate what I mean.
std::array<int, 3> ai {1, 2, 3} ;
std::array<double, 3> ad {1.0, 2.0, 3.0} ;
std::array<std::string, 3> as {"a", "b", "c"} ;
You see?
-
It’s a bit too much text on the left-hand side of the variable name.
-
The 3rd declaration is even questionable if the correct type is used.
Create some syntax sugar
Let’s improve this following the test driven approach.
First some usage code
auto ai = array(1, 2, 3) ;
auto ad = array(1.0, 2.0, 3.0) ;
auto as = array("a", "b", "c") ;
Isn’t this much better? I think it is.
For this to work I need a function that does the dirty work for me.
The function that constructs the array looks like this
template<typename... Args>
std::array<typename std::common_type<Args...>::type, sizeof...(Args)>
array(Args&&... args)
{
return std::array<typename std::common_type<Args...>::type,
sizeof...(Args)>{ std::forward<Args>(args)... };
}
And I think, the as
from above will have a much better fitting type.
Please note that this may break code containing a using std::array
.
In this case the function should be called something different, like, make_array
maybe.
- Here is the copy and paste version
-
for your favourite online compiler
#include <iostream>
#include <array>
template<typename... Args>
std::array<typename std::common_type<Args...>::type, sizeof...(Args)>
array(Args&&... args)
{
return std::array<typename std::common_type<Args...>::type,
sizeof...(Args)>{ std::forward<Args>(args)... };
}
int main()
{
auto chars = array("a", "b", "c") ;
for (auto& c : chars)
std::cout << c << std::endl ;
for (auto& d : array(1.0, 2.0, 3.0))
std::cout << d << std::endl ;
}
If you find any mistakes, in the code or in my spelling, please add a comment below, ideas for improvements are also very much welcome.