当类没有constexpr构造函数时,简化冗余std :: array初始化

时间:2018-02-10 19:21:37

标签: c++ arrays c++11 variadic-templates template-meta-programming

我有以下代码的更复杂版本:

#include <array>
#include <cmath>

using namespace std;

class Dummy
{
    public:
        Dummy(const double a, const double f)
        {
            //Some complex calculations
        }
};

constexpr double values[] { 0.1, 0.2, 0.3, 0.4 };
constexpr auto N = sizeof(values) / sizeof(values[0]);
static const array<Dummy, N> dummies {Dummy(10 * values[0], M_PI * 0),
                                      Dummy(10 * values[1], M_PI * 1),
                                      Dummy(10 * values[2], M_PI * 2),
                                      Dummy(10 * values[3], M_PI * 3)};

int main()
{
    //Complex use of dummies
    return 0;
}

我想简化dummies数组的初始化,因为它是高度冗余的。但是,我受C ++ 11的约束,我无法将Dummy类更改为constexpr构造函数(这将极大地简化我的情况)。

我查看了可变参数模板,但似乎无法解决Dummy的构造函数不是constexpr这一事实:

template<size_t... Is>
struct _Helper
{
    static constexpr array<Dummy, N> dummies {Dummy(10 * values[Is], M_PI * Is)...}; //Fails to compile because Dummy's constructor is not constexpr
};

static const array<Dummy, N> dummies { _Helper<0, 1, 2, 3>::dummies };

还有其他方法可以简化数组的初始化吗? values可以重新声明为其他任何可以在运行时转换回double[]的内容。

2 个答案:

答案 0 :(得分:3)

也许你可以按如下方式创建一个make函数

getData

并使用它来初始化

template <std::size_t ... Is>
std::array<Dummy, sizeof...(Is)> makeDummArr (double const * vals)
 { return { { Dummy(10 * vals[Is], M_PI * Is)... } }; } }

很遗憾你被C ++ 11绑定了:如果你的static const std::array<Dummy, N> dummies = makeDummArr<0, 1, 2, 3>(values); 列表是顺序的(从零开始)和一个长列表,那么你是否可以使用C ++ 14。 ..所以Is...std::make_index_sequence ...

我的意思是

std::index_sequence

(或者您可以遵循HolyBlackCat的建议,并在C ++ 11中创建template <std::size_t ... Is> std::array<Dummy, sizeof...(Is)> makeDummArr (double const * vals, std::index_sequence<Is...> const &) { return { { Dummy(10 * vals[Is], M_PI * Is)... } }; } static const std::array<Dummy, N> dummies = makeDummArr(values, std::make_index_sequence<4U>{}); std::index_sequence的替代品

答案 1 :(得分:2)

以下代码与@ max66建议的相似,
但并不要求您手动输入0, 1, ..., N-1

template <int ...I> struct int_seq // A rip-off of C++14 std::index_sequence.
{
    template <int X> using push_back = int_seq<I..., X>;
};
template <int N> struct make_int_seq_impl
{
    using type = typename make_int_seq_impl<N-1>::type::template push_back<N-1>;
};
template <> struct make_int_seq_impl<0>
{
    using type = int_seq<>;
};
template <int N> using make_int_seq = typename make_int_seq_impl<N>::type;

template <int ...I> array<Dummy, N> make_dummies(int_seq<I...>)
{
    return {Dummy(10 * values[I], M_PI * I)...};
}

static const array<Dummy, N> dummies = make_dummies(make_int_seq<N>{});