如何在 C++ 预处理器宏中处理数组元素?

How can I process array elements in a c++ preprocessor macro?

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

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

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

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

这是一个使用 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";
}

请注意,您不 "return" 来自宏。宏是文本替换。在上面出现 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";
}

预处理器本质上做了很多查找和替换操作。它没有任何真正高级的功能,当然也不知道数组是什么。我想这个作业要求你做的是编写一些内联代码来对数组或其他东西求和,然后为它创建一个宏。

#define fold(array, ln, acc, op) \
  for(size_t i = 0; i < ln; ++i) \
    acc = acc op array[i];

int main(){
  int ar[10];
  int sum = 0;
  fold(ar, 10, sum, *); 
}

此代码使用 * 操作折叠数组。