c++ - int 参数为 : conditional expressions ignored? 的意外模板行为

标签 c++ templates

以下代码未按预期工作(或至少如我所料)。我尝试的所有 g++ 版本都在模板递归限制下失败。输出似乎表明条件语句被忽略,并且无论 P 的值如何都使用最后的 else block 。

template <int P> inline REAL const_pow   ( REAL value );
template <     > inline REAL const_pow<0>( REAL value ) { return 1.0; }
template <     > inline REAL const_pow<1>( REAL value ) { return value; }
template <     > inline REAL const_pow<2>( REAL value ) { return value*value; }

template <int P> inline REAL const_pow   ( REAL value ) 
{
  if (P < 0)
    return const_pow<-P>( 1.0/value );
  else if (P % 2 == 0)
    return const_pow<2>( const_pow<P/2>(value) );
  else
    return value * const_pow<P-1>( value );
}

问题似乎不在于负值(唯一)。如果我重新排序条件,使负值情况排在最后,最后一个 block 仍然每次都被采用。

我有一个使用辅助类和更复杂的特化的工作解决方案。但是这个版本更具可读性并且应该达到相同的效果(启用优化)。为什么它不起作用?

最佳答案

请记住,在实际执行开始之前,所有 分支都需要编译(在模板求值时求值)!出于这个原因,const_pow<3>将尝试实例化 const_pow<-3>即使它最终永远不会运行。作为返回需要 const_pow<3>再次……

您需要的是完全禁用不正确分支的模板评估。这可以通过手动制作的类型特征或通过 C++11 std::enable_if 来解决。 .

尝试以下操作:

#include <iostream>
typedef float REAL;

template <int P> inline REAL const_pow   ( REAL value );
template <     > inline REAL const_pow<0>( REAL value ) { return 1.0; }
template <     > inline REAL const_pow<1>( REAL value ) { return value; }
template <     > inline REAL const_pow<2>( REAL value ) { return value*value; }

template <int P, bool negative>
struct const_pow_helper { //instantiate this when P is positive
        static inline REAL call(REAL value) {
                return const_pow<2>(const_pow<P / 2>(value)) * const_pow<P % 2>(value);
        }
};

template <int P>
struct const_pow_helper<P, true> { //instantiate this when P is negative
        static inline REAL call(REAL value) {
                return const_pow_helper<-P, false>::call(1.0/value);
        }
};

template <int P> inline REAL const_pow   ( REAL value )
{
        return const_pow_helper<P, P<0 >::call(value);
}

int main() {
        std::cout << const_pow<10>(2.0f) << std::endl;
        std::cout << const_pow<-10>(2.0f) << std::endl;
};

请注意 const_pow_helper 的负版本将仅针对负 P 进行实例化.这个决定由模板评估器处理,而不是普通的 if .

if对于积极的P通过使用整数除法 (P/2) 也被避免了并乘以余数(如果存在)(P%2) .

关于c++ - int 参数为 : conditional expressions ignored? 的意外模板行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23940744/

相关文章:

c++ - 检测文本文件中的特定字符串

c++ - 编译错误 - 静态成员

c++ - 对 C++ 嵌套依赖类型名称感到困惑

c++ - 如何仅从类类型推断类构造函数的参数类型

c++ - 简单类的GCC去虚拟化

c++ - std::vector<{QString,int*}> 的奇怪行为

c++ - 模板 C++ 数组

c++ - 递归调用模板类的成员函数

c++ - CUDA - 将 cpu 代码与 cuda 代码分开

c++ - 自定义结构和关系重载生成错误