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



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

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

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

当我以函数的风格编写宏时,我不知道如何将总和"返回"给程序。我能想到的让宏扩展到总和的唯一方法是如果它是递归完成的,我什至不确定你是否可以用宏递归。我已经编写了一个成功扩展到数组大小的宏,但我不确定从那里开始的方向。

以下是使用 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";
}

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

#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, *); 
}

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

最新更新