c++ - 表达式包含未扩展的参数包

标签 c++ templates c++11 variadic-templates

不知何故,我不明白可变参数模板参数包是如何扩展的。以下代码有什么问题?

#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' 和 'args'。为什么?

最佳答案

... 必须放在函数调用括号内:

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

显然,这不适用于只接受单个参数的函数,因此您需要找到一种方法将调用扩展为函数调用或其他允许的构造:

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

注意使用逗号运算符将 print_onevoid 返回值转换为适合放置在参数列表或初始化表达式中的值。

初始化列表形式优于函数调用形式,因为它们(应该是)有序的 LTR 而函数调用参数不是。

14.5.3 [temp.variadic] 涵盖了可以发生参数包扩展的形式:

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

  • [...]

您的原始代码是非法的,因为尽管从文本上看,它可能会生成一个由多个逗号运算符表达式组成的语句,但这不是 14.5.3:4 所允许的上下文。

关于c++ - 表达式包含未扩展的参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12515616/

相关文章:

c++ - 如何使用 Qt 中的默认程序打开服务器上的文件?

c++ - QJsonDocument::fromRawData(const char *data, int size) 数据必须与 4 字节边界对齐

C++虚拟模板函数

c++ - 可以使用内联命名空间来保持共享库的向后兼容性吗?

c++ - 安装 dlib 时出错

c++ - 用户定义的转换运算符优先级,在 g++ 中编译但在 clang++ 中不编译

c++ - 使用 qFromBigEndian 从 Char 转换为 Int 表示 : "No matching function for call to"

c++ - DirectX、引用计数和智能指针

C++ 模板和以基类和子类作为模板参数的转换

c++ - 模板函数的差异