表达式包含未展开的参数包 [英] Expression contains unexpanded parameter packs

查看:357
本文介绍了表达式包含未展开的参数包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何展开可变参数模板参数包。下面的代码有什么问题?

Somehow I don't get how variadic template parameter packs are expanded. What's wrong with thie following code?

#include <iostream>

template <typename T>
struct print_one
{
    static void run(const T& t)
    {
        std::cout << t << ' ';
    }
};

template<typename... Args>
void print_all(Args&&... args)
{
    // the next line doesn't compile:
    print_one<Args>::run(std::forward<Args>(args))...;
}

int main()
{
    print_all(1.23, "foo");
}

Clang说,表达式包含未展开的参数包'和'args'。为什么?

Clang says, Expression contains unexpanded parameter packs 'Args' and 'args'. Why?

推荐答案

... 调用括号:

print_one<Args>::run(std::forward<Args>(args)...);

很明显,这不会对你的函数只有一个参数,所以你需要找到一种方法将调用扩展为函数调用或其他允许的构造:

Obviously, that won't work for your function that takes only a single argument, so you need to find a way to expand the calls into a function call or other allowed construct:

// constructing a dummy array via uniform initialization
// the extra 0 at the start is to make it work when the pack is empty
int dummy[]{0, (print_one<Args>::run(std::forward<Args>(args)), 0)...};

// or, if your compiler doesn't support uniform initialization
int dummy[] = {0, (print_one<Args>::run(std::forward<Args>(args)), 0)...};

// or, calling a dummy function
template<typename... Args> void dummy(Args...) {}
dummy((print_one<Args>::run(std::forward<Args>(args)), 0)...);

// or, constructing a temporary dummy object
struct dummy { dummy(std::initializer_list<int>) {} };
dummy{(print_one<Args>::run(std::forward<Args>(args)), 0)...};

// or, constructing a temporary initializer list
std::initializer_list<int>{(print_one<Args>::run(std::forward<Args>(args)), 0)...};

请注意使用逗号运算符来转换 void 返回 print_one 为适合放入参数列表或初始化器表达式的值。

Note the use of the comma operator to turn the void return of print_one into a value suitable to place in an argument list or initializer expression.

-list表单比函数调用表单更喜欢,因为它们(应该是)有序LTR,函数调用参数不是。

The initializer-list forms are preferred to the function call forms, as they are (supposed to be) ordered LTR which function call arguments are not.

参数包扩展可以发生的问题包括在14.5.3 [temp.variadic]中:

The forms where a parameter pack expansion can occur are covered by 14.5.3 [temp.variadic]:


4 - [...]上下文:

4 - [...] Pack expansions can occur in the following contexts:


  • [...]

您的原始代码是非法的,因为虽然文本上它可能看起来应该产生一个由多个逗号运算符表达式组成的语句,这不是14.5.3:4允许的上下文。

Your original code is illegal because although textually it might appear that it should produce a statement consisting of a number of comma-operator expressions, that is not a context allowed by 14.5.3:4.

这篇关于表达式包含未展开的参数包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆