C++17当使用可变模板参数(参数包)时,fold表达式和if constexpr之间的区别是什么



我正在努力理解处理参数包/可变模板参数的两种方法之间的区别。

下面的链接文章中提到了两种方法。

  • 折叠表达式
  • if constexpr(我不知道它是否有正式名称(

文章链接

我特别想知道编译器是如何编译这两种方法的,以及输出是否是单个函数,或者输出是否包含递归函数调用。

更广泛地说,如果有什么需要注意的话,使用这两种方法的优点或缺点是什么。

(我是从是否有可能从过多嵌套函数调用中产生堆栈溢出的角度来考虑这个问题的。(

我对文章中所写内容的解释是,if constexpr方法在编译后会产生多个单个函数调用,每个函数调用一个,每个函数的参数数量不同。

然而,我可能误解了这一点。

换言之,我将其解释为,如果程序包含对变参数模板函数的两个函数调用,其中一个函数调用包含3个参数,另一个包含5个参数,那么编译器将生成两个单独的函数,一个包含3个自变量,一个含5个自变量。但我可能错了。

有人能澄清一下情况吗?

首先,这个:

template <class... Ts>
void print_all(std::ostream& os, Ts const&... args) {
((os << args), ...);
}

是一个模板,每次调用只生成一个函数,如下所示:

print_all(std::cout, "hello", ' ', "there", 5, "arguments");

其次,这个:

template <class T, class... Ts>
void print_all(std::ostream& os, T const& first, Ts const&... rest) {
os << first;
if constexpr (sizeof...(rest) > 0) {        
// this line will only be instantiated if there are further
// arguments. if rest... is empty, there will be no call to
// print_all(os). 
print_all(os, rest...);
}
}

是一个模板,它将为同一调用生成5个函数。案例如下:

  • print_all(std::cout, "hello", ' ', "there", 5, "arguments")
  • print_all(std::cout, ' ', "there", 5, "arguments")
  • print_all(std::cout, "there", 5, "arguments")
  • print_all(std::cout, 5, "arguments")
  • print_all(std::cout, "arguments")

Fold表达式是操作参数包的一种简单方法:

template<typename ...Args>
void print(const Args& ...args) {
(std::cout << ... << args) << std::endl;
}

这是一个将展开...的句法暗示。(如果没有fold表达式,则必须使用template<typename F, typename ...Args>并递归以获取...中的every(


if constexpr是在comile时间运行的if语句。

template<typename T>
auto print_type_info(const T& t) {
if constexpr (std::is_integral<T>::value) {
return t + 1;
} else {
return t + 0.001;
}
}
// Compiler will instancelize it like:
int print_type_info(const int& t) {
return t + 1;
}
double print_type_info(const double& t) {
return t + 0.001;
}

结论:它们只是更干净的语法,在使用时没有明显的问题。

这只是我的理解。如果有任何错误,请告诉我。:(

最新更新