尝试使用带有单个非类型模板参数的模板函数

问题描述 投票:0回答:1

我尝试了避免递归的程序版本:

#include <iostream>

template <int N>
constexpr int factorial()
{
  int value = 1; // 0! = 1
  for (int i = 1; i <= N; i++)
  {
    value *= i;
  }
  return value;
}

int main(int argc, const char * argv[])
{
  std::cout << factorial<5>() << std::endl;
  
  return 0;
}

它有效,并返回 120,正如预期的那样。

但是,当我尝试使用递归时,它会失败并出现编译时错误。

#include <iostream>

template <int N>
constexpr int factorial()
{
  if (N == 0) return 1;
  return N * factorial<N - 1>();
}

int main(int argc, const char * argv[])
{
  std::cout << factorial<5>() << std::endl;
  
  return 0;
}

稍后我将详细介绍编译时错误...

我尝试了递归版本,预计它会给我 120,非递归版本也是如此。

我在 iMac 上使用 XCode,使用 GCC++17。递归版本给了我以下错误:

Factorial Template
/Users/bryanhiggs/C++ Development/Factorial Template/Factorial Template/main.cpp
/Users/bryanhiggs/C++ Development/Factorial Template/Factorial Template/main.cpp unable to execute command: Illegal instruction: 4

/Users/bryanhiggs/C++ Development/Factorial Template/Factorial Template/main.cpp clang frontend command failed due to signal (use -v to see invocation)

diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
diagnostic msg: /var/folders/zv/nww97t6d3yl_xskx2_k5_jlr0000gn/T/main-5df374.cpp
diagnostic msg: /var/folders/zv/nww97t6d3yl_xskx2_k5_jlr0000gn/T/main-5df374.sh
diagnostic msg: Crash backtrace is located in
diagnostic msg: /Users/bryanhiggs/Library/Logs/DiagnosticReports/clang_<YYYY-MM-DD-HHMMSS>_<hostname>.crash
diagnostic msg: (choose the .crash file that corresponds to your crash)
diagnostic msg: 

********************

这是 GCC++17 中的错误,还是我误解了什么?

templates gcc
1个回答
0
投票

你的基本情况不起作用。编译器会为

N
= 0 删除一个函数,如下所示:

template <>
constexpr int factorial<0>()
{
  if (0 == 0) return 1;
  return N * factorial<0-1>();
}

当然,它确实返回

1
,但该函数仍然包含表达式
factorial<N - 1>()
,因此必须将其删除。

有两种方法可以解决这个问题:

使用
if constexpr

template <int N>
constexpr int factorial()
{
  // A compile-time if which drops the non-hitting block immediately
  if constexpr (N == 0) return 1;
  else return N * factorial<N - 1>();
}

对基本案例使用专业化

// General function for any N other than 0
template <int N>
constexpr int factorial()
{
  return N * factorial<N - 1>();
}

// Specialization for N=0
template<>
constexpr int factorial<0>
{
  return 1;
}
© www.soinside.com 2019 - 2024. All rights reserved.