C++ 17 使用可变参数模板参数(参数包)时,折叠表达式和 if constexpr 有什么区别

发布于 2025-01-19 03:16:54 字数 659 浏览 6 评论 0原文

我试图理解处理参数包/可变参数模板参数的两种方法之间的区别。

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

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

链接到文章

具体来说,我有兴趣知道编译器如何编译这两种方法,以及输出是否是单个函数,或者输出是否包含递归函数调用。

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

(我从是否有可能因过多的嵌套函数调用而产生堆栈溢出的角度来思考这一点。)

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

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

换句话说,我将其解释为如果程序包含对可变参数模板函数的两个函数调用,并且其中一个函数调用包含 3 个参数,另一个包含 5 个参数,则编译器会生成两个单独的函数,其中一个函数带有3 个参数,一个与 5 个参数。但我对此可能是错的。

谁能澄清一下情况吗?

I am trying to understand the difference between two approaches for handling parameter packs / variadic template arguments.

There are two approaches mentioned in the linked article below.

  • fold expression
  • if constexpr (I don't know if this has a formal name)

Link to article

Specifically I am interested to know how the compiler compiles these two approaches, and whether the output is a single function, or whether the output contains recursive function calls.

And more broadly, what are the advantages or disadvantages of using either method, if there are any to be aware of.

(I am thinking about this from the point of view of whether it might be possible to produce a stack overflow from too many nested function calls.)

My interpretation of what is written in the article is that the if constexpr method produces multiple single function calls once compiled, one for each function call which differs by the number of arguments.

However I may have misinterpreted this.

In other words, I interpreted this to mean that if the program contains two function calls to the variadic template function, and one of those function calls contains 3 parameters, and the other contains 5 parameters, then the compiler produces two separate functions, one with 3 arguments, and one with 5. But I may be wrong about this.

Can anyone clarify the situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笨笨の傻瓜 2025-01-26 03:16:54

首先,这

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”,'','','',5,“参数”)
  • print_all(std :: cout :: cout,''', “那里”,5,“参数”)
  • print_all(std :: cout,“ were”,5,gragments')
  • print_all(std :: cout,5,5,5, “参数”)
  • print_all(std :: cout,“ granments”)

First, this:

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

is a template that will generate only one function per call like so:

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

Secondly, this:

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...);
    }
}

is a template that will generate 5 functions for the same call. The cases are as follows:

  • 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")
飘逸的'云 2025-01-26 03:16:54

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

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

它是一个将展开 ... 的语法糖。 (如果没有折叠表达式,则必须使用 template 并递归获取 ... 中的每个内容)


if constexpr< /code> 是在 comile-time 运行的 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;
}

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

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

Fold expression is a easy way to operate a parameter pack:

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

It's a syntactic suger that will unfold the .... (Without fold expression, you must use template<typename F, typename ...Args> and recurs to get every in the ...)


if constexpr is if statement run in comile-time.

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;
}

Conclusion:
They are just cleaner syntaces and have no explicit problem while using.

It's my understanding just. If there's any error, please tell me. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文