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

Apply same function to each element of N arrays of different sizes

本文关键字:数组 元素 功能 应用于      更新时间:2023-10-16

让我们考虑使用构造函数和成员函数foo实现的类A

这是一些代码:

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

对于每个数组。

最短,最简单的方法是什么,而无需连续写下九个横环?

您很可能希望将代码打包到特定的初始化功能中。由于(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;
}

您只需在每个数组上调用此功能即可。如果还不够短,则可以将其包装到variadic模板函数中:

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, ...);

您可能会做类似:

的事情
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>();
//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();
        }
    });