You can use the C ++ 0x auto keyword along with the template specialization , for example, with the name boost::make_array() (similar to make_pair() ). For the case when N is 1 or 2 arguments, we can then write option A as
namespace boost { template <typename T> boost::array<T,1> make_array(const T & a) { return boost::array<T,2> ({{ a }}); } template <typename T> boost::array<T,2> make_array(const T & a, const T & b) { return boost::array<T,2> ({{ a, b }}); } }
and option B as
namespace boost { template <typename T> boost::array<T,1> make_array(const T & a) { boost::array<T,1> x; x[0] = a; return x; } template <typename T> boost::array<T,2> make_array(const T & a, const T & b) { boost::array<T,2> x; x[0] = a; x[1] = b; return x; } }
GCC-4.6 with -std=gnu++0x and -O3 generates the same binary for
auto x = boost::make_array(1,2);
using both A and B as for
boost::array<int, 2> x = {{1,2}};
For user-defined types (UDTs), however, option B leads to an additional copy constructor , which usually slows down and should therefore be avoided.
Note that boost::make_array when called with explicit char array literals, as in the following case
auto x = boost::make_array("a","b");
I believe this is good, since const char* literals can be deceiving when using them.
Variadic templates , available in GCC since version 4.5, can be used to reduce the template specialization code label code for each N in the definition of one template boost::make_array() is defined as
template <typename T, typename ... R> boost::array<T,1+sizeof...(R)> make_array(T a, const R & ... b) { return boost::array<T,1+sizeof...(R)>({{ a, b... }}); }
This works pretty much as we expect. The first argument defines the boost::array template T argument, and all other arguments are converted to T In some cases, this may be undesirable, but I'm not sure how this can be indicated using variation patterns.
Perhaps boost::make_array() should go into Boost libraries?