将相同的函数应用于大小不同的N个数组的每个元素

时间:2019-02-24 16:38:16

标签: c++ arrays for-loop c++17

我们考虑一个具有构造函数和成员函数A的类foo

以下是一些代码:

constexpr int size1 = 100;
constexpr int size2 = 13;
constexpr int size3 = 48;
constexpr int size4 = 231;
constexpr int size5 = 5;
constexpr int size6 = 125;
constexpr int size7 = 88;
constexpr int size8 = 549;
constexpr int size9 = 417;

int main(void)
{
    std::array<A*, size1> array1;
    std::array<A*, size2> array2;
    std::array<A*, size3> array3;
    std::array<A*, size4> array4;
    std::array<A*, size5> array5;
    std::array<A*, size6> array6;
    std::array<A*, size7> array7;
    std::array<A*, size8> array8;
    std::array<A*, size9> array9;

    // Solution

    return 0;
}

我想构造每个数组的每个元素,然后为每个数组调用成员函数foo

基本上,我想这样做:

for (auto& element : array1)
{
    element = new A();
    element->foo();
}

每个数组。

最简单快捷的方法是什么,而不必连续写下9个for循环?

3 个答案:

答案 0 :(得分:2)

您可能会做类似的事情:

template <std::size_t N>
using As = std::array<A*, N>;

std::tuple<As<size1>, As<size2>, As<size3>, As<size4>, As<size5>,
           As<size6>, As<size7>, As<size8>, As<size9>> arrays;

std::apply([](auto& ...as)
          {
              auto l = [](auto& a)
              {
                for (auto& element : a)
                {
                    element = new A();
                    element->foo();
                }
              };
              (l(as), ...);
          }, arrays);

或更简单:

template <size_t N>
std::array<A*, N> MakeAs()
{
    std::array<A*, N> res;
    for (auto& element : res)
    {
        element = new A();
        element->foo();
    }
    return res;
}

auto array1 = MakeAs<size1>();
auto array2 = MakeAs<size2>();
auto array3 = MakeAs<size3>();
auto array4 = MakeAs<size4>();
auto array5 = MakeAs<size5>();
auto array6 = MakeAs<size6>();
auto array7 = MakeAs<size7>();
auto array8 = MakeAs<size8>();
auto array9 = MakeAs<size9>();

答案 1 :(得分:2)

您很可能希望将代码打包到特定的初始化函数中。由于长度不同的(std::)数组实际上是不同的类型,因此,您要么需要模板函数,要么需要对数组的内部原始数组(data())进行操作:

template <typename T>
void initialize(T& t)
{
    for(auto& a : t)
    //      ^ reference to pointer (!)
    {
        a = new A();
        a->foo();
    }
    std::cout << std::endl;
}

然后您只需在每个数组上调用此函数。如果还不够短,您可以将其打包到可变参数模板函数中:

template <typename T, typename ... TT>
void initialize(T& t, TT& ... tt)
{
    initialize(t);
    initialize(tt...);
}

// alternatively, a bit shorter, with C++17 fold expression:
template <typename ... TT>
void initialize(TT& ... tt)
{
    (initialize(tt), ...);
}

在通话时,这很可能是您能获得的最短的时间(除了选择一个更短的名称之外):

initialize(array1, array2, array3, array4, ...);

答案 2 :(得分:1)

//C++ 11 SFINAE fold
template<size_t I = 0, typename F, typename ...Ts>
typename std::enable_if<I == sizeof...(Ts)>::type       //I == end
    for_each(std::tuple<Ts...>&, const F&) {}


template<size_t I = 0, typename F, typename ...Ts>
typename std::enable_if<I < sizeof...(Ts)>::type        //I < end
    for_each(std::tuple<Ts...>& tuple, const F& function)
{
    function(std::get<I>(tuple));
    for_each<I + 1>(tuple, function);
}

//C++ 17
template<size_t I = 0, typename F, typename ...Ts>
void for_each(std::tuple<Ts...>& tuple, const F& function)
{
    if constexpr(I < sizeof...(Ts))
    {
        function(std::get<I>(tuple));
        for_each<I + 1>(tuple, function);
    }
}

//Client
for_each(std::tie(array1, array2, array3, array4, array5, array6, array7, array8, array9), 
    [](auto& array)
    { 
        for(auto* element : array)
        {
           element = new A();
           element->foo();
        }
    });