我知道如果我实例化一个模板,例如:
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只能使用四个值之一调用。
简单地说编译器必须在需要实例化的四个单独的函数模板周围放入一个条件流(实际上我试图避免手动操作)并且它不知道如何?
有更优雅的方式吗?
编辑:为了澄清 - 不那么简单的实现使用整数值来应用函数中的类型选择的一些元程序。
答案 0 :(得分:2)
我想你几乎用你的尝试解释了它。
看待事物的独立方式很简单,你提供的模板参数值必须是编译时已知的常量。由于您提供的值是一个在运行时才知道的变量,因此根本不允许这样做。
是的,在这种特殊情况下,具有不错的优化器的编译器可能会找出需要为您提供的四种情况提供的四个常量值。
虽然有很多案例可能不那么明确。例如,包含某些特定优化的编译器可以确定某个特定值实际上是编译时常量的情况,但另一个缺少该特定优化的情况不会知道它。
面对一个他们无法回答的问题(“编译器能否在编译时推断出这个值?”)委员会采取了相当保守的方法,并指定了相对较窄的允许输入范围。当然,编译器可以选择接受其他表达式作为扩展名。
从委员会的角度来看,我认为添加constexpr
是尝试相当普遍地实现至少非常相似的东西 - 允许以一种让编译器知道的方式完成更大范围的计算结果应该可用作编译时常量。考虑到实现这一点的复杂性,我的猜测是,对于像上面给出的情况那样强制编译时计算是不可能的(至少在不久的将来)。
答案 1 :(得分:1)
由于你没有告诉我们使用你的函数的模板参数的“不那么微不足道”的方法,我会说出来解决这个问题的方法是通过去模板化你的函数而只是传递运行时参数。
然后您不必在任何地方进行运行时到编译时值转换,在所有情况下,该值都会在运行时传递。
换句话说:int ReturnMeDouble(int i) { ... }