首页 > 解决方案 > 如何在 C++ 预处理器宏中处理数组元素?

问题描述

对于家庭作业,我们被要求编写一个预处理器宏来对数组的元素求和。

我的问题是,如何以可以扩展为总和(或元素上的任何其他数学运算)的方式处理宏中的数组元素?

我们的书中没有提到处理数组元素甚至访问它们,而且我在网上找不到很多有用的资源,因为宏不是处理此类事情的典型方法。我知道有更好的方法来做这样的事情,但我知道这个想法是为了让我们更好地熟悉预处理器宏。

当我以函数的形式编写宏时,我不知道如何将总和“返回”给程序。我能想到的让宏扩展为总和的唯一方法是递归完成,我什至不确定你是否可以使用宏进行递归。我编写了一个成功扩展为数组大小的宏,但我不确定从那里往哪个方向发展。

标签: c++arraysmacrospreprocessor-directive

解决方案


这是使用 c++14 的答案:

#include <array>
#include <iostream>
#include <numeric>
#include <type_traits>
#include <vector>

#define SUM(ARY) \
  std::accumulate( \
      std::begin(ARY), \
      std::end(ARY), \
      std::remove_reference_t<decltype(ARY[0])>{})
int
main()
{
  auto ary1 = std::array< int, 5 >{1,2,3,4,5};
  std::cout << SUM(ary1) << "\n";

  int ary2[] = {1,2,3,4,5};
  std::cout << SUM(ary2) << "\n";

  auto ary3 = std::vector< int >{1, 2, 3, 4, 5};
  std::cout << SUM(ary3) << "\n";

  double ary4[] = {1.1,2.2,3.3,4.4,5.5};
  std::cout << SUM(ary4) << "\n";
}

请注意,您不会从宏中“返回”。宏是文本替换。在上面出现的地方,它被宏定义SUM(ary)的扩展文本替换。SUM(ARY)

您可以将此扩展到其他操作:

#include <array>
#include <iostream>
#include <numeric>

#define OP_ON_ARY(ARY, OP) \
  std::accumulate( \
      std::next(std::begin(ARY)), \
      std::end(ARY), \
      *std::begin(ARY), \
      [](auto a, auto b) { return a OP b; } \
      )

int
main()
{
  auto ary = std::array< int, 5 >{1,2,3,4,5};
  std::cout << OP_ON_ARY(ary, +) << "\n";
  std::cout << OP_ON_ARY(ary, -) << "\n";
  std::cout << OP_ON_ARY(ary, *) << "\n";
}

但是使用函数而不是宏更符合现代 c++ 的精神。

#include <array>
#include <iostream>
#include <numeric>
#include <vector>

template< typename Ary >
auto sum(Ary const & ary)
{
  return std::accumulate(
      std::begin(ary),
      std::end(ary),
      decltype(ary[0]){});
}

int
main()
{
  auto ary1 = std::array< int, 5 >{1,2,3,4,5};
  std::cout << sum(ary1) << "\n";

  int ary2[] = {1,2,3,4,5};
  std::cout << sum(ary2) << "\n";

  auto ary3 = std::vector< int >{1, 2, 3, 4, 5};
  std::cout << sum(ary3) << "\n";

  double ary4[] = {1.1,2.2,3.3,4.4,5.5};
  std::cout << sum(ary4) << "\n";
}

推荐阅读