3

我知道,如果我实例化一个模板,例如:

template<int i>
int ReturnMeDouble()
{
    return 2 * i;
}

然后编译器需要能够在编译时评估 i 的值。我的问题是(为简单起见而简化)我希望我的程序根据变量调用两个函数之一。我的代码看起来像这样:

int returnValue = 0;
switch(value)
{
    case 1:
    case 2:
    case 3:
    case 4:
        returnValue = ReturnMeDouble<value>();
        break;
    case 5:
    case 6:
        returnValue = ReturnMeTriple<value>();
        break;
}

真正的 ReturnMe... 函数做了一些不那么琐碎的事情。现在很明显,我可以使用这个 switch 语句并在每个 case 语句下提供单独的调用,但我只是想知道我是否缺少某些东西,因为在第一种情况下对我来说(如果不是编译器的话)似乎很明显, ReturnMeDouble 只能用四个值之一调用。

仅仅是编译器必须围绕需要实例化的四个单独的函数模板(实际上是我试图避免手动执行的操作)放置一个条件流并且它不知道如何?

有没有更优雅的方式来做到这一点?

编辑:澄清 - 不太简单的实现使用整数值来应用一些元程序以在函数内进行类型选择。

4

2 回答 2

2

认为您的尝试解释已经非常成功了。

看待事物的标准方式很简单,您作为模板参数提供的值必须是编译时已知的常量。由于您提供的值是一个直到运行时才知道的变量,所以根本不允许这样做。

是的,在这种特定情况下,具有良好优化器的编译器可能会计算出您给出的四种情况需要提供的四个常量值。

不过,还有很多情况可能不太明确。例如,包含某些特定优化的编译器可以确定特定值实际上是编译时常量,但另一个缺少特定优化的编译器不会知道它。

面对一个他们无法回答的问题(“编译器可以在编译时推导出这个值吗?”),委员会采取了相当保守的方法,并指定了一个相对狭窄的允许输入范围。当然,编译器可以选择接受其他表达式作为扩展。

从委员会的角度来看,我认为添加constexpr是对至少相当相似的东西的相当普遍的实现的尝试——允许以一种让编译器知道结果应该作为编译可用的方式完成更大范围的计算-时间常数。考虑到实现的复杂性,我的猜测是,对于你上面给出的情况强制编译时计算是不可能的(至少在不久的将来)。

于 2013-05-15T14:28:50.463 回答
1

由于您没有告诉我们使用函数模板参数的“不那么琐碎”的方式,我要出去说解决这个问题的方法是对您的函数进行去模板化并传递一个运行时范围。

然后,您不必在任何地方进行运行时到编译时值的转换,在所有情况下,值只是在运行时传递。

换句话说:int ReturnMeDouble(int i) { ... }

于 2013-05-15T14:26:51.707 回答