【问题标题】:Overloading function calls for compile-time constants重载函数调用编译时常量
【发布时间】:2015-04-22 14:34:03
【问题描述】:

我很想知道是否可以区分使用编译时常量提供的参数的函数调用和不使用的函数调用?

例如:

int a = 2;
foo( a )  // #1: Compute at run-time
foo( 3 )  // #2: Compute at compile-time

有没有办法提供区分这两种情况的重载?或者更一般地说,我如何检测文字类型的使用?

我研究过 constexpr,但函数参数不能是 constexpr。使用相同的调用语法,但能够根据参数是否为字面量类型生成不同的代码会很整洁。

【问题讨论】:

  • 如果有constexpr int foo(int x) noexcept;那么foo(3)不会在编译时计算?
  • @Arun,会的。但是,您无法在 foo 中判断调用是在编译时还是运行时进行的。

标签: c++ c++11


【解决方案1】:

您无法区分编译时文字 int 和运行时变量 int。如果你需要这样做,你可以提供一个只能在编译时工作的重载:

void foo(int ); // run-time

template <int I>
void foo(std::integral_constant<int, I> ); // compile-time

【讨论】:

  • 为什么要一路使用std::integral_constant?对于简单的用例,您可以在template &lt;int I&gt; void foo(); 停下来。没有?
  • @RSahu 我只是发现在某些情况下已经将其作为参数更方便,所以我一直都这样做。当然,你可以这样做foo&lt;x&gt;()
【解决方案2】:

我认为上述答案在某种程度上错过了问题试图提出的观点。

有没有办法提供区分这两种情况的重载?或者更一般地说,我如何检测文字类型的使用?

这就是“右值引用”的用途。文字类型是一个右值。

如果有相同的调用语法,但能够根据参数是否为字面类型生成不同的代码,那就太好了。

你可以简单地重载你的 foo() 函数:

void foo(int&& a);

因此,当您使用文字调用函数时,例如foo(3),编译器知道你需要上面的重载,因为 3 是一个右值。如果将函数调用为 foo(a),编译器将选择您的原始版本 foo(const int&amp; a);,因为 int a=2; 是左值。

这为您提供了相同的调用语法。

【讨论】:

  • 当然,右值!事实上,重点是使重载解决方案起作用。非常感谢!
  • foo(a + 3) 怎么样?像foo(a + b) 这样的调用不会调用这个右值重载吗?从这个问题来看,我不确定这是要求。
  • 这很好,@Arun。我没有比给出的例子更进一步。但我也不确定这是否是他的要求。
  • @Arun 是的,这最终会破坏我的问题的目的。尽管如此,我最初的问题没有提到这一点,因此鉴于响应解决了给定示例这一事实,我将把它标记为答案。
【解决方案3】:

在一般情况下,您无法在编译时评估 foo(3)。如果 foo(x) 被定义为将 x 天添加到当前日期 - 并且您在下周二首先运行该程序会怎样?如果它确实是一个常数,那么使用一个符号常数。如果它是一个简单的函数,您可以尝试定义(将在编译时替换为实现 - 但仍将在运行时进行评估)

例如

#define MIN(x,y) ((x)<(y)?(x):(y))

【讨论】:

  • 例如,这只是一个简单的宏函数——我认为提问者想要一个简单的函数替换,但他想要编译时评估。我的错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多