【问题标题】:Apply same function to each element of N arrays of different sizes [closed]对不同大小的 N 个数组的每个元素应用相同的函数 [关闭]
【发布时间】:2019-02-24 16:38:16
【问题描述】:

让我们考虑一个类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();
}

对于每个数组。

在不连续写下九个 for 循环的情况下,最短和最简单的方法是什么?

【问题讨论】:

  • 数组元组,并在两者上“迭代”?
  • 你不能在元组、数组、跨度或 std::array 中获取你的大小吗?
  • 我对@9​​87654326@ 不太满意,这解释了为什么这个问题与我有关。在我点击“提交”后的前 30 分钟内,出现了三个详细且解释清楚的答案。如果问题不好,没人会打扰。我不明白负分。
  • 我相信这是一个 XY 问题。你想要什么 - 就实际用例而言?例如A 在你的程序中实际上是什么意思? .... std::vector 或 MACRO 可能是一个答案。

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


【解决方案1】:

您很可能希望将代码打包到特定的初始化函数中。但是,由于 (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, ...);

【讨论】:

  • 可能(initialize(tt), ...); 为 C++17
【解决方案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>();

【讨论】:

  • CreateAsMakeAs。无论如何,绝对是最好的一个。另外,如果数组不能放入元组,可以简单地std::forward_as_tuple()它们。
  • @Deduplicator 可能会很麻烦,但std::tie 也应该可以解决问题,无论如何我们都有左值引用,甚至更短...
【解决方案3】:
//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();
        }
    });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多