将#define内容作为参数传递

时间:2016-01-12 02:57:11

标签: c++

我有一个很长的算法应该处理从多个#define描述的一些指令,以便大大减少我的源代码。例如:

#define LongFunction(x, y, alg) return alg(x, y)
#define Alg1(x, y) ((x)+(y))
#define Alg2(x, y) ((x)^((x)-(y)))

我需要做的就是

LongFunction(x, y, Alg1);
LongFunction(x, y, Alg2);

我不想将函数作为参数传递,因为LongFunction充满了循环,我希望代码尽可能快。我怎样才能巧妙地完成这项任务?

1 个答案:

答案 0 :(得分:3)

有很多方法可以参数化函数。

使用宏看起来很简单,但宏不考虑范围,参数替换和副作用存在问题,所以它们是Evil™

在C ++ 11及更高版本中,最自然的选择是使用std::function和lambdas,如下所示:

#include <functional>       // std::function
#include <math.h>           // pow
using std::function;

auto long_function(
    double const x,
    double const y,
    function<auto(double, double) -> double> alg
    )
    -> double
{
    // Whatever.
    return alg( x, y );     // Combined with earlier results.
}

auto alg1(double const x, double const y)
    -> double
{ return x + y; }

auto alg2(double const x, double const y)
    -> double
{ return pow( x, x - y ); }

#include <iostream>
using namespace std;
auto main() -> int
{
    cout << long_function( 3, 5, alg1 ) << endl;
}

关于“尽可能快”,使用现代编译器,宏代码可能不会更快。但由于这很重要,请衡量。对于版本构建和典型执行环境,只有测量可以告诉您什么是最快的以及速度是否与最终用户相关。

旧的,并且正式地,您可以使用inline说明符来向编译器提示它应该对函数进行内联调用。现代编译器可能只是忽略了inline(它有另一个更有保障的含义,即ODR)。但是应用它可能不会有害。同样,衡量也很重要。请注意,结果可能因编译器而异。

上面的一个替代方法是传递一个简单的函数指针。这可能比std::function更快,但不太通用。但是,在另一个方向上,您可以使用成员函数对类型进行模板化,这样可以为编译器提供更多信息,更多内联机会,代价是无法以在运行时从数组中选择操作。我相信,当你测量时,如果这很重要,你会发现模板化产生最快的代码。或者至少和上面一样快。

提供操作的类型上的模板化示例:

#include <math.h>           // pow

template< class Op >
auto long_function( double const x, double const y )
    -> double
{
    // Whatever.
    return Op()( x, y );     // Combined with earlier results.
}

struct Alg1
{
    auto operator()(double const x, double const y)
        -> double
    { return x + y; }
};

struct Alg2
{
    auto operator()(double const x, double const y)
        -> double
    { return pow( x, x - y ); }
};

#include <iostream>
using namespace std;
auto main() -> int
{
    cout << long_function<Alg1>( 3, 5 ) << endl;
}

顺便提一下,请注意 ^ 不是C ++中的取幂运算符(它在例如Visual Basic中)。在C和C ++中,它是一个小级的XOR运算符。在上面的代码中,我假设你真的是指取幂,并使用pow中的<math.h>函数。

相反,如果你真的意味着等级XOR,那么参数需要是整数(最好是无符号整数),这表示你需要long_function的参数类型,具体取决于指定的参数类型操作。这是一个棘手的问题,但涉及过载或模板,或两者兼而有之。如果那是你真正想要的,那么请详细说明。