Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何检查内联函数的参数在编译时是否已知?_C++_Static_Constants_Inline - Fatal编程技术网

C++ 如何检查内联函数的参数在编译时是否已知?

C++ 如何检查内联函数的参数在编译时是否已知?,c++,static,constants,inline,C++,Static,Constants,Inline,我有一个性能关键的内联函数。它根据一个参数生成一些数据。我希望编译器优化所有调用的数据生成,其中参数在编译时是已知的。问题是,我不能强制编译器将优化后的数据从堆栈中放入一个静态常量,因为标记datastatic将打破参数不是编译时常量的情况。堆栈上有恒定数据会影响性能。有没有办法推断(可能使用templates/boost::enable_if)参数是编译时常量,并选择适当的数据生成实现 澄清 基本上我有以下几点: struct Data { int d_[16]; }; inlin

我有一个性能关键的内联函数。它根据一个参数生成一些数据。我希望编译器优化所有调用的数据生成,其中参数在编译时是已知的。问题是,我不能强制编译器将优化后的数据从堆栈中放入一个静态常量,因为标记data
static
将打破参数不是编译时常量的情况。堆栈上有恒定数据会影响性能。有没有办法推断(可能使用templates/boost::enable_if)参数是编译时常量,并选择适当的数据生成实现

澄清

基本上我有以下几点:

struct Data {
     int d_[16];
};

inline Data fun(int param)
{  //param can sometimes be a compile-time constant

    ... //generate the data
    Data res = {gen0, gen2, gen3, ..., gen15}; //put the data into result
    return res;
}
因此,当
param
不是编译时常量时,我们只需生成所有数据并返回。
param
已知时,编译器可以优化数据生成。但是,它无法优化下面的行输出并生成大量代码,这些代码只是将
res
成员设置为已知数据(数据嵌入到程序代码中)。我希望编译器创建一个静态常量,然后将其复制到返回对象(这比使用嵌入数据执行许多代码要快)。由于这是一个内联函数,因此甚至可能不需要复制

免责声明


这个问题和我的不一样。这是一个更普遍的问题。

我不相信有任何方法可以做到这一点;编译器的责任是优化调用,而不是语言的。。。因此,没有便携的方法可以做到这一点:\

听起来你有:

template <int N> myfunc_const_N() { /*...*/ }
inline myfunc_var_N(int N);
模板myfunc_const_N(){/*…*/}
内联myfunc_var_N(int N);
您希望能够键入
myfunc(n)
并让编译器调用
myfunc_const_N()如果有效或
myfunc\u var\u N(N)如果没有

我猜这是不可能的,但这很难证明


但如果你能做到,这真的会给你带来很多好处吗?在代码编写时,有多少次您不知道给定的表达式是否是编译时常量?如果确实有常量,为什么不自己使用模板版本,如果没有常量,为什么不使用函数参数版本?

如果函数是内联的,那么编译器将在适当的情况下在内联函数时执行常量折叠优化,假设您有一个相当合理的编译器。

您是否确实分析了代码并证明将常量传递给(内联?)函数是瓶颈


如果您确实进行了分析,那么您必须帮助编译器解决这个问题,因为无法自动完成。如果知道常量和正常版本,则必须手动调用函数的模板版本。

这是不可移植的,但在GCC和可能的Clang上有一个编译器函数。这使您可以询问编译器是否知道编译时变量的值。您可以这样使用它:

void f(int arg) {
  if (__builtin_constant_p(arg) && arg == 0) {
    // Handle case where arg is 0 AND known at compile time.
  } else {
    // Generic code.
  }
}
这样,如果
arg
在编译时已知且为0,编译器将不会在
else
分支中生成代码

一个有用的技巧是使用一点宏黑客技术,使其更具可移植性

#ifdef __GNUC__
#  define CONSTANT_P(x) __builtin_constant_p(x)
#else
#  define CONSTANT_P(x) 0
#endif

根据需要添加其他支持类似于此的编译器,您现在可以在不支持此功能的编译器上使用此功能,而无需额外开销。也就是说,如果这些编译器有任何价值,它们将消除
常量\u P
分支,只留下泛型代码。

我认为没有办法检测函数参数是否是编译时常量,我不明白你为什么要重新命名旧问题,所以标题与问题相矛盾,然后开始新的问题。不,新标题与问题不矛盾。我在编辑中错误地表达了自己,直到现在才意识到这一点。谢谢优化后的函数速度提高了20%(整个函数,而不是加载阶段)。看起来,如果大常量立即嵌入到代码中(参见我的编辑),那么每次都会重新生成整个常量,即使我不需要所有数据。这种情况在嵌入式系统中经常出现。例如,在某些ST micros上,一些端口寄存器将引脚0映射到位0、引脚1映射到位1、引脚2映射到位2等。其他端口寄存器将引脚0映射到位0-1、引脚1映射到位2-3、引脚2映射到位4-5等。如果要对由使用“引脚n=位n”掩码计算的掩码定义的一组I/O引脚执行操作,则可能必须使用这些位生成一个掩码“展开”。如果掩码是常量,则编写扩展代码的最佳方法是将表达式计算为编译时常量。但是,如果掩码不是常量,则计算表达式所需的……代码将非常糟糕,最好调用函数调用进行转换。