为什么在带参数包的递归中需要 constexpr

koe*_*egl 0 c++ templates if-constexpr

我有一个简单的递归函数来打印参数包中的每个参数

#include <iostream>

template<typename T, typename... Args>
void printArgs(T first, Args... rest) {
    std::cout << first << " ";
    
    if constexpr (sizeof...(rest) > 0) { // doesn't compile without constexpr
        printArgs(rest...);
    } else {
        return;
    }
}

int main() {
    printArgs(1, 2, "hello");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Q1:为什么程序需要constexpr编译?Q2:条件不应该是吗?因为如果大小是,我再次调用,那么不会是空的?(空着可以吗?)if
sizeof...(rest) > 11printArgsrest

我看到了类似的问题,例如“constexpr if”与“if”的优化 - 为什么需要“constexpr”?,但我不明白这些答案与我的案例有什么关系。

for*_*818 5

我将从第二个问题开始,因为该问题的答案也解释了问题1。

Q2:条件不应该是吗sizeof...(rest) > 1?因为如果大小为1,我printArgs再次调用,那么不会rest是空的吗?(空着可以吗?)

你的错误是要算Tsizeof...(rest)。但如果你调用printArgs(onlyOne)then则从andT推导出来为空,并且is 。您的函数可以使用 1 ( ) 加上零个或多个 ( ) 参数来调用。onlyOneArgssizeof...(rest)0T firstArgs... rest

Q1:为什么程序编译时需要在 if 中使用 constexpr?

如果删除,constexpr您会收到以下错误

<source>: In instantiation of 'void printArgs(T, Args ...) [with T = const char*; Args = {}]':
<source>:8:18:   recursively required from 'void printArgs(T, Args ...) [with T = int; Args = {const char*}]'
<source>:8:18:   required from 'void printArgs(T, Args ...) [with T = int; Args = {int, const char*}]'
<source>:15:14:   required from here
<source>:8:18: error: no matching function for call to 'printArgs()'
    8 |         printArgs(rest...);
      |         ~~~~~~~~~^~~~~~~~~
<source>:4:6: note: candidate: 'template<class T, class ... Args> void printArgs(T, Args ...)'
    4 | void printArgs(T first, Args... rest) {
      |      ^~~~~~~~~
<source>:4:6: note:   template argument deduction/substitution failed:
<source>:8:18: note:   candidate expects at least 1 argument, 0 provided
    8 |         printArgs(rest...);
      |         ~~~~~~~~~^~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

因为在最后一次递归中,仅传递了 1 个参数printArgs并且rest没有元素。在这种情况下,printArgs(rest...)编译失败,因为(见上文)你的函数只能用 1 或更多来调用。if constexpr导致错误分支被丢弃,并且您调用的部分printArgs()永远不会被实例化。