C++11 constexpr函数中如何使用统一值初始化数组

6
我有一个类模板,它的一个成员是基于模板参数构建的简单数组。我需要能够在其中一个构造函数中初始化数组中的每个元素为单个值。不幸的是,这个构造函数必须是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}进行初始化仅设置数组的第一个元素并将其余元素初始化为零。

如何实现?

我觉得可以使用可变参数模板和元组等方式解决...


@BryanChen:不是很相关,那个问题与constexpr无关。 - Ben Voigt
如果“foo(T val)”的构造函数参数能够转换为模板参数“template <T val> foo()”,则可以简单地实现您想要的功能。 - oakad
2个回答

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))
    {}
};

我将POD数组替换为std::array - 假设它不会对您的用例造成任何问题。

这里是实时示例:http://coliru.stacked-crooked.com/a/4731a10ee54563b9


1
+1 也可以在函数中指定返回类型,与 -std=c++11 兼容。http://coliru.stacked-crooked.com/a/668bd7f546654971 - Praetorian
当然 - 不知怎么的,decltype() 在我的脑海中溜走了。 - oakad

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)) {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接