我有一个类模板,它根据模板参数构建一个简单的数组作为其成员之一。我需要能够将数组中的每个元素初始化为其中一个构造函数中的单个值。不幸的是,这个构造函数必须是constexpr
。
相关部分归结为:
template <typename T, size_t N>
class foo
{
T data[N];
constexpr foo(T val)
{
// initialize data with N copies of val
}
};
使用std::fill
或循环与constexpr
要求不兼容。使用: data{val}
初始化仅设置数组的第一个元素,并对剩余部分进行零初始化。
如何实现这一目标?
我觉得应该有可变模板和元组等的解决方案......
答案 0 :(得分:8)
相当奇怪的是,问题的解决方案存在于c ++ 14中(在gcc上使用-std=c++1y
编译示例;另请参阅Praetorian的更详细的c ++ 11解决方案的注释):
template <size_t N>
struct bar {
template <typename T, typename ...Tn>
static constexpr auto apply(T v, Tn ...vs)
{
return bar<N - 1>::apply(v, v, vs...);
}
};
template <>
struct bar<1> {
template <typename T, typename ...Tn>
static constexpr auto apply(T v, Tn ...vs)
{
return std::array<T, sizeof...(vs) + 1>{v, vs...};
}
};
template <typename T, size_t N>
struct foo {
std::array<T, N> data;
constexpr foo(T val)
: data(bar<N>::apply(val))
{}
};
(我用std :: array替换了POD数组 - 假设它不会对你的用例造成任何问题。)
现场示例在这里:http://coliru.stacked-crooked.com/a/4731a10ee54563b9
答案 1 :(得分:6)
您可以使用以下内容:(https://ideone.com/xTacMP)
namespace detail
{
template <typename T, std::size_t...Is>
constexpr std::array<T, sizeof...(Is)> make_array(T val, index_sequence<Is...>)
{
return {(static_cast<void>(Is), val)...};
}
}
template <std::size_t N, typename T>
constexpr std::array<T, N> make_array(T val)
{
return detail::make_array(val, make_index_sequence<N>());
}
然后叫它:
constexpr foo(T val) : data(make_array<N>(val)) {}