您可以在名为boost::make_array()
(类似于make_pair()
)的函数上,结合C++0xauto
关键字和模板特化使用。对于N
是1或2个参数的情况,我们可以将变体A表述为:
namespace boost
{
/*! Construct Array from @p a. */
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 }});
}
}
并且将变体B视为
namespace boost {
/*! Construct Array from @p a. */
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使用-std=gnu++0x
和-O3
编译时,生成的二进制代码完全相同。
auto x = boost::make_array(1,2);
它同时使用A和B,就像它对待其它技术一样。
boost::array<int, 2> x = {{1,2}};
对于用户定义类型(UDT),变体B会产生一个额外的复制构造函数,通常会减慢速度,因此应该避免使用。
请注意,在以下情况下使用显式字符数组文字调用boost::make_array
时会出现错误:
auto x = boost::make_array("a","b");
我认为这是一件好事,因为const char*
字面值在使用时可能会产生误导。
Variadic templates自GCC 4.5以来可用,可以进一步用于将每个N
的所有模板专业化样板代码减少到一个boost :: make_array()
的单个模板定义中。
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... }});
}
这个功能基本上符合我们的预期。第一个参数确定了boost::array
模板参数T
,而所有其他参数都被转换为T
。对于某些情况,这可能是不希望的,但我不确定是否可以使用可变模板来指定。
也许boost::make_array()
应该加入Boost库中?
struct
替代class
不是更容易吗?我发现编译通过的代码更容易学习 ;-) - Steve Jessop